#ifndef __EMP_QUEUE_H__
#define __EMP_QUEUE_H__

#include <slave.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#ifdef TARG_SW5
#include "dma.h"
#endif
#ifdef TARG_SW9
#include "crts.h"
#include "simd.h"
#endif
#ifdef DEBUG
#include <assert.h>
#endif
// #include "MemPool.h"
// #include "args.h"

#include "aceMesh_utils.h"
#include "emp_basic.h"

#define ROLE_G_SERVER 0
#define ROLE_L_SERVER 1
#define ROLE_CLIENT 2
#define ROLE_DEFAULT 4
#define ROLE_M_SERVER 5

#ifdef SLAVE_CONSTRUCT_HELEPR
#include "helper_slave.h"
// __thread_local_fix int begin_execute[64]={1};
#endif

#ifdef EMP_MASTER

#define OP_PUSH_SL 0
#define OP_PUSH_MS 1

#else

#define OP_PUSH 0

#endif

#ifdef MULTI_PUSH
#define OP_MULTI_PUSH 1
#endif

#define OP_POP_REQ 2
#define OP_POP_REPLY 3
#define OP_EXIT 4
#ifdef SLAVE_CONSTRUCT_HELEPR
extern __thread_local_fix int helper_flag;
__thread_local int global_heleper=0;
#ifdef DISTRIBUTE_TOP
__thread_local_fix int top_sig=0;
__thread_local_fix struct top_level_buff tl_buffer[NT];
// __thread_local_fix struct buffer_tasks buffer_tasks_list[64];
// __thread_local struct top_level toptask; 
#endif
#endif

/*
#ifdef EMP_MASTER
    #if defined(LDM_QUEUE) || defined(HIER_QUEUE_LIFO)
#define INITIAL_MASTER_QUEUE_SIZE 1024
    #else
#define INITIAL_MASTER_QUEUE_SIZE 32768
    #endif
#endif

#if defined(LDM_QUEUE) || defined(HIER_QUEUE_LIFO)
#define INITIAL_QUEUE_SIZE 4096
    #ifdef HIER_QUEUE_LIFO
//#define HIER_MEM_QUEUE_SIZE 131072
#define HIER_MEM_QUEUE_SIZE 4194304
    #endif
#else
//#define INITIAL_QUEUE_SIZE 131072
#define INITIAL_QUEUE_SIZE 4194304
#endif
*/
#ifdef TARG_SW5
#define ROW(x) ((x & 0x38) >> 3)
#define COL(x) (x & 0x7)

#ifdef EMP_WORKER_CONF
#define WORKERS 56  // from 1 to 56
#endif

__thread_local_fix uint8_t my_role, my_row, my_col;
//__thread_local_fix volatile int eq_status;
//__thread_local_fix volatile uint64_t eq_ptr_slot;
volatile int eq_status;
volatile uint64_t eq_ptr_slot;

/*
#if !defined(LDM_QUEUE) && !defined(HIER_QUEUE_LIFO)
struct task * big_array[INITIAL_QUEUE_SIZE];
    #ifdef EMP_MASTER
struct task * master_big_array[INITIAL_MASTER_QUEUE_SIZE];
    #endif
#endif
*/

#ifdef HIER_QUEUE_LIFO
struct task *mem_queue[HIER_MEM_QUEUE_SIZE];
__thread_local_fix unsigned mem_queue_tail = 0;
#endif

#ifndef EMP_PUT_FULL_PROF

#define REG_PUTR(var, dst)                                 \
    {                                                      \
        asm volatile("putr %0,%1\n" ::"r"(var), "r"(dst)); \
    }
#define REG_PUTC(var, dst)                                 \
    {                                                      \
        asm volatile("putc %0,%1\n" ::"r"(var), "r"(dst)); \
    }

#else

static inline int PUT_FULL(void)
{
    int var;
    asm volatile("rcsr %0,0x36\n" : "=r"(var));
    return var;
}
#define PUTR_MACRO(var, dst)                               \
    {                                                      \
        asm volatile("putr %0,%1\n" ::"r"(var), "r"(dst)); \
    }
#define PUTC_MACRO(var, dst)                               \
    {                                                      \
        asm volatile("putc %0,%1\n" ::"r"(var), "r"(dst)); \
    }

void REG_PUTR(uint256 v, unsigned dst, unsigned *put_count, unsigned *put_full)
{
    if (PUT_FULL()) {
        *put_full = *put_full + 1;
    }
    PUTR_MACRO(v, dst);
    *put_count = *put_count + 1;
}

void REG_PUTC(uint256 v, unsigned dst, unsigned *put_count, unsigned *put_full)
{
    if (PUT_FULL()) {
        *put_full = *put_full + 1;
    }
    PUTC_MACRO(v, dst);
    *put_count = *put_count + 1;
}

#endif

#define REG_GETR(var)                          \
    {                                          \
        asm volatile("getr %0\n" : "=r"(var)); \
    }
#define REG_GETC(var)                          \
    {                                          \
        asm volatile("getc %0\n" : "=r"(var)); \
    }

#define EQ_start() if (my_role == ROLE_CLIENT) {
#define EQ_end()                       \
    }                                  \
    else if (my_role == ROLE_L_SERVER) \
    {                                  \
        EQ_local_server();             \
    }                                  \
    else if (my_role == ROLE_G_SERVER) \
    {                                  \
        EQ_global_server();            \
    }                                  \
    else                               \
    {                                  \
        ;                              \
    }

static inline int EMPTY_GETR(void)
{
    int var;
    asm volatile("rcsr %0,0x34\n" : "=r"(var));
    return var;
}
static inline int EMPTY_GETC(void)
{
    int var;
    asm volatile("rcsr %0,0x35\n" : "=r"(var));
    return var;
}

#if defined(GLD) || defined(GST)
__thread_local_fix unsigned long push_gld_count1, push_gld_count2, pop_gld_count1, pop_gld_count2;
__thread_local_fix unsigned long push_gld, pop_gld;
extern unsigned long gld[64];
#endif

#ifdef EMP_QUEUE_PROFILING
unsigned max_length;
#endif

#ifdef EMP_PUT_FULL_PROF
unsigned gs_put_count = 0;
unsigned gs_put_full = 0;
unsigned ls_put_count[7] = {0};
unsigned ls_put_full[7] = {0};
unsigned worker_put_count[64] = {0};
unsigned worker_put_full[64] = {0};
#endif

#ifdef EMP_MASTER
//__thread_local_fix volatile int m2s_flag = BUFF_STATUS_MS;
volatile int m2s_flag = BUFF_STATUS_MS;
extern volatile master_buff m2s_pending;
#endif

struct msg_content {
    uint16_t op;
    uint16_t my_row;
    uint16_t my_col;
    uint16_t padding;
    uint64_t value[3];
};

typedef union EQ_msg {
    uint256 v;
    struct msg_content m;
} EQ_msg_t;

/*
typedef struct EQ_queue {
#if defined(LDM_QUEUE) || defined(HIER_QUEUE_LIFO)
    struct task * array[INITIAL_QUEUE_SIZE];
#else  // MMEM_QUEUE
    struct task ** array;
#endif
    unsigned size;
    unsigned head;
    unsigned tail;
} EQ_queue;


#ifdef EMP_MASTER
typedef struct EQ_master_queue {
#if defined(LDM_QUEUE) || defined(HIER_QUEUE_LIFO)
    struct task * array[INITIAL_MASTER_QUEUE_SIZE];
#else   // MMEM_QUEUE
    struct task ** array;
#endif
    unsigned size;
    unsigned head;
    unsigned tail;
} EQ_master_queue;
#endif
*/

#ifdef EMP_MASTER
inline int EQ_queue_full(void *queue_ptr, int is_master)
#else
inline int EQ_queue_full(EQ_queue *queue)
#endif
{
#ifdef EMP_MASTER
    if (is_master) {
        EQ_master_queue *queue = (EQ_master_queue *)queue_ptr;
        return (queue->tail - queue->head) == queue->size;
    } else {
        EQ_queue *queue = (EQ_queue *)queue_ptr;
        return (queue->tail - queue->head) == queue->size;
    }
#else
    return (queue->tail - queue->head) == queue->size;
#endif
}

#ifdef EMP_MASTER
inline int EQ_queue_empty(void *queue_ptr, int is_master)
#else
inline int EQ_queue_empty(EQ_queue *queue)
#endif
{
#ifdef EMP_MASTER
    if (is_master) {
        EQ_master_queue *queue = (EQ_master_queue *)queue_ptr;
        return queue->tail == queue->head;
    } else {
        EQ_queue *queue = (EQ_queue *)queue_ptr;
        return queue->tail == queue->head;
    }
#else
    return queue->tail == queue->head;
#endif
}

inline unsigned EQ_queue_length(EQ_queue *queue) { return queue->tail - queue->head; }

#ifdef EMP_MASTER
inline unsigned EQ_queue_space(EQ_queue *queue) { return queue->size - EQ_queue_length(queue); }
#endif

#ifdef EMP_MASTER
void EQ_queue_gs_push(void *queue_ptr, struct task *t, int is_master)
#else
void EQ_queue_gs_push(EQ_queue *queue, struct task *t)
#endif
{
#ifdef GLD
    penv_slave2_gld_count(&push_gld_count1);
#elif GST
    penv_slave2_gst_count(&push_gld_count1);
#endif

#ifdef EMP_MASTER

    if (is_master) {
        EQ_master_queue *queue = (EQ_master_queue *)queue_ptr;
#ifdef EMP_CONCURRENT_Q
        slave_my_mutex_lock(&(queue->my_q_lock));
#endif
        if (!EQ_queue_full(queue, 1)) {
            queue->array[queue->tail % queue->size] = t;
            queue->tail++;
        } else {
            printf("master queue full!!!!!!!\n");
        }
#ifdef EMP_CONCURRENT_Q
        slave_my_mutex_unlock(&(queue->my_q_lock));
#endif
    } else {
        EQ_queue *queue = (EQ_queue *)queue_ptr;
#ifdef EMP_CONCURRENT_Q
        slave_my_mutex_lock(&(queue->my_q_lock));
#endif
        if (!EQ_queue_full(queue, 0)) {
#ifdef HIER_QUEUE_LIFO
            queue->array[queue->tail] = t;
#else
            queue->array[queue->tail % queue->size] = t;
#endif
            queue->tail++;
        } else {
#ifdef HIER_QUEUE_LIFO
            if ((HIER_MEM_QUEUE_SIZE - mem_queue_tail) >=
                (INITIAL_QUEUE_SIZE / 2)) {  // still has space
                int tsize = (INITIAL_QUEUE_SIZE / 2) * sizeof(struct task *);
                volatile unsigned long dma_reply = 0;
                athread_put(0, queue->array, mem_queue + mem_queue_tail, tsize, (void *)&dma_reply,
                            0, 0);
                while (dma_reply != 1)
                    ;
                asm volatile("memb\n");  // there has to be a 'memb' here, dunno why
                mem_queue_tail += INITIAL_QUEUE_SIZE / 2;
                memcpy(queue->array, queue->array + INITIAL_QUEUE_SIZE / 2, tsize);
                queue->tail = INITIAL_QUEUE_SIZE / 2;
                queue->array[queue->tail] = t;
                queue->tail++;
            } else {
                printf("slave mem queue full!!!!!!!\n");
            }
#else
            printf("slave queue full!!!!!!!\n");
#endif
        }
#ifdef EMP_CONCURRENT_Q
        slave_my_mutex_unlock(&(queue->my_q_lock));
#endif
    }

#else
#ifdef EMP_CONCURRENT_Q
    slave_my_mutex_lock(&(queue->my_q_lock));
#endif
    if (!EQ_queue_full(queue)) {
#ifdef HIER_QUEUE_LIFO
        queue->array[queue->tail] = t;
#else
        queue->array[queue->tail % queue->size] = t;
#endif
        queue->tail++;
#ifdef EMP_QUEUE_PROFILING
        unsigned qlen = EQ_queue_length(queue);
        if (max_length < qlen) max_length = qlen;
#endif

#ifdef GLD
        penv_slave2_gld_count(&push_gld_count2);
        push_gld += push_gld_count2 - push_gld_count1;
#elif GST
        penv_slave2_gst_count(&push_gld_count2);
        push_gld += push_gld_count2 - push_gld_count1;
#endif
    } else {
#ifdef HIER_QUEUE_LIFO
        if ((HIER_MEM_QUEUE_SIZE - mem_queue_tail) >= (INITIAL_QUEUE_SIZE / 2)) {  // still has
                                                                                   // space
            int tsize = (INITIAL_QUEUE_SIZE / 2) * sizeof(struct task *);
            volatile unsigned long dma_reply = 0;
            athread_put(0, queue->array, mem_queue + mem_queue_tail, tsize, (void *)&dma_reply, 0,
                        0);
            while (dma_reply != 1)
                ;
            asm volatile("memb\n");  // there has to be a 'memb' here, dunno why
            mem_queue_tail += INITIAL_QUEUE_SIZE / 2;
            memcpy(queue->array, queue->array + INITIAL_QUEUE_SIZE / 2, tsize);
            queue->tail = INITIAL_QUEUE_SIZE / 2;
            queue->array[queue->tail] = t;
            queue->tail++;
        } else {
            printf("mem queue full!!!!!!!\n");
        }
#else
        printf("queue full!!!!!!!\n");
#endif
#ifdef GLD
        penv_slave2_gld_count(&push_gld_count2);
        push_gld += push_gld_count2 - push_gld_count1;
#elif GST
        penv_slave2_gst_count(&push_gld_count2);
        push_gld += push_gld_count2 - push_gld_count1;
#endif
#ifdef EMP_CONCURRENT_Q
        slave_my_mutex_unlock(&(queue->my_q_lock));
#endif
        return;
    }
#ifdef EMP_CONCURRENT_Q
    slave_my_mutex_unlock(&(queue->my_q_lock));
#endif
#endif
}

#ifdef EMP_MASTER
struct task *EQ_queue_gs_pop(void *queue_ptr, int is_master)
#else
struct task *EQ_queue_gs_pop(EQ_queue *queue)
#endif
{
#ifdef EMP_MASTER
    if (is_master) {
        EQ_master_queue *queue = (EQ_master_queue *)queue_ptr;
#ifdef EMP_CONCURRENT_Q
        slave_my_mutex_lock(&(queue->my_q_lock));
#endif
        if (!EQ_queue_empty(queue, 1)) {
            struct task *temp = queue->array[queue->head % queue->size];
            queue->head++;
#ifdef EMP_CONCURRENT_Q
            slave_my_mutex_unlock(&(queue->my_q_lock));
#endif
            return temp;
        } else {
#ifdef EMP_CONCURRENT_Q
            slave_my_mutex_unlock(&(queue->my_q_lock));
#endif
            return NULL;
        }
    } else {
        EQ_queue *queue = (EQ_queue *)queue_ptr;
#ifdef EMP_CONCURRENT_Q
        slave_my_mutex_lock(&(queue->my_q_lock));
#endif

        if (!EQ_queue_empty(queue, 0)) {
#ifdef HIER_QUEUE_LIFO
            queue->tail--;
            struct task *temp = queue->array[queue->tail];
#else
            struct task *temp = queue->array[queue->head % queue->size];
            queue->head++;
#endif
#ifdef EMP_CONCURRENT_Q
            slave_my_mutex_unlock(&(queue->my_q_lock));
#endif
            return temp;
        } else {
#ifdef HIER_QUEUE_LIFO
            if (mem_queue_tail >= (INITIAL_QUEUE_SIZE / 2)) {  // mem queue not empty
                int tsize = (INITIAL_QUEUE_SIZE / 2) * sizeof(struct task *);
                volatile unsigned long dma_reply = 0;
                mem_queue_tail -= INITIAL_QUEUE_SIZE / 2;
                athread_get(0, mem_queue + mem_queue_tail, queue->array, tsize, (void *)&dma_reply,
                            0, 0, 0);
                while (dma_reply != 1)
                    ;
                asm volatile("memb\n");  // there has to be a 'memb' here, dunno why
                queue->tail = INITIAL_QUEUE_SIZE / 2;
                queue->tail--;
                struct task *temp = queue->array[queue->tail];
#ifdef EMP_CONCURRENT_Q
                slave_my_mutex_unlock(&(queue->my_q_lock));
                assert(0);
#endif
                return temp;
            } else {
#ifdef EMP_CONCURRENT_Q
                slave_my_mutex_unlock(&(queue->my_q_lock));
                assert(0);
#endif
                return NULL;
            }
#endif
#ifdef EMP_CONCURRENT_Q
            slave_my_mutex_unlock(&(queue->my_q_lock));
#endif
            return NULL;
        }
    }

#else

#ifdef GLD
    penv_slave2_gld_count(&pop_gld_count1);
#elif GST
    penv_slave2_gst_count(&pop_gld_count1);
#endif

#ifdef EMP_CONCURRENT_Q
    slave_my_mutex_lock(&(queue->my_q_lock));
#endif

    if (!EQ_queue_empty(queue)) {
#ifdef HIER_QUEUE_LIFO
        queue->tail--;
        struct task *temp = queue->array[queue->tail];
#else
        struct task *temp = queue->array[queue->head % queue->size];
        queue->head++;
#endif
#ifdef GLD
        penv_slave2_gld_count(&pop_gld_count2);
        pop_gld += pop_gld_count2 - pop_gld_count1;
#elif GST
        penv_slave2_gst_count(&pop_gld_count2);
        pop_gld += pop_gld_count2 - pop_gld_count1;
#endif
#ifdef EMP_CONCURRENT_Q
        slave_my_mutex_unlock(&(queue->my_q_lock));
#endif
        return temp;
    } else {
#ifdef GLD
        penv_slave2_gld_count(&pop_gld_count2);
        pop_gld += pop_gld_count2 - pop_gld_count1;
#elif GST
        penv_slave2_gst_count(&pop_gld_count2);
        pop_gld += pop_gld_count2 - pop_gld_count1;
#endif
#ifdef HIER_QUEUE_LIFO
        if (mem_queue_tail >= (INITIAL_QUEUE_SIZE / 2)) {  // mem queue not empty
            int tsize = (INITIAL_QUEUE_SIZE / 2) * sizeof(struct task *);
            volatile unsigned long dma_reply = 0;
            mem_queue_tail -= INITIAL_QUEUE_SIZE / 2;
            athread_get(0, mem_queue + mem_queue_tail, queue->array, tsize, (void *)&dma_reply, 0,
                        0, 0);
            while (dma_reply != 1)
                ;
            asm volatile("memb\n");  // there has to be a 'memb' here, dunno why
            queue->tail = INITIAL_QUEUE_SIZE / 2;
            queue->tail--;
            struct task *temp = queue->array[queue->tail];
#ifdef EMP_CONCURRENT_Q
            slave_my_mutex_unlock(&(queue->my_q_lock));
            assert(0);
#endif
            return temp;
        } else {
#ifdef EMP_CONCURRENT_Q
            slave_my_mutex_unlock(&(queue->my_q_lock));
            assert(0);
#endif
            return NULL;
        }
#endif
#ifdef EMP_CONCURRENT_Q
        slave_my_mutex_unlock(&(queue->my_q_lock));
#endif
        return NULL;
    }

#endif
}

void EQ_begin()
{
    int core_id;
    core_id = athread_get_id(-1);
    my_row = ROW(core_id);
    my_col = COL(core_id);
#ifdef EMP_WORKER_CONF
    int trans_id = (my_col - 1) * 8 + my_row;
    int local_server_limit;
    if (WORKERS >= 8)
        local_server_limit = 7;
    else
        local_server_limit = WORKERS - 1;
    if (core_id == 0) {
        my_role = ROLE_G_SERVER;
    } else if (my_col == 0 && my_row <= local_server_limit) {
        my_role = ROLE_L_SERVER;
    } else if (my_col != 0 && trans_id < WORKERS) {
        my_role = ROLE_CLIENT;
    } else {
        my_role = ROLE_DEFAULT;
    }
#else
    if (core_id == 0) {
        my_role = ROLE_G_SERVER;
    } else if (my_col == 0) {
        my_role = ROLE_L_SERVER;
    } else {
        my_role = ROLE_CLIENT;
    }
#endif
}

#ifdef EMP_MASTER
inline void EQ_init_queue(void *queue_ptr, int is_master)
#else
inline void EQ_init_queue(EQ_queue *queue)
#endif
{
    // InitPool();
    // queue->array = (struct task **)mempool_myalloc_aligned_8(INITIAL_QUEUE_SIZE * sizeof(struct
    // task *));
#ifdef EMP_MASTER
    if (is_master) {
        EQ_master_queue *queue = (EQ_master_queue *)queue_ptr;
#if !defined(LDM_QUEUE) && !defined(HIER_QUEUE_LIFO)  // MMEM_QUEUE
        queue->array = master_big_array;
#ifdef EMP_CONCURRENT_Q
        queue->my_q_lock = 0;
#endif
#endif
        queue->head = 0;
        queue->tail = 0;
        queue->size = INITIAL_MASTER_QUEUE_SIZE;
        eq_status = STATUS_IDLE;
    } else {
        EQ_queue *queue = (EQ_queue *)queue_ptr;
#if !defined(LDM_QUEUE) && !defined(HIER_QUEUE_LIFO)  // MMEM_QUEUE
        queue->array = big_array;
#ifdef EMP_CONCURRENT_Q
        queue->my_q_lock = 0;
#endif
#endif
        queue->head = 0;
        queue->tail = 0;
        queue->size = INITIAL_QUEUE_SIZE;
        eq_status = STATUS_IDLE;
    }

#else

#if !defined(LDM_QUEUE) && !defined(HIER_QUEUE_LIFO)  // MMEM_QUEUE
    queue->array = big_array;
#ifdef EMP_CONCURRENT_Q
    queue->my_q_lock = 0;
#endif
#endif
    queue->head = 0;
    queue->tail = 0;
    queue->size = INITIAL_QUEUE_SIZE;
    eq_status = STATUS_IDLE;
#ifdef EMP_QUEUE_PROFILING
    max_length = 0;
#endif

#endif
}

inline void EQ_destroy_queue()
{
    // FreePool();
    ;
}

#if defined(EMP_MASTER) && defined(EMP_CONCURRENT_Q)
extern EQ_master_queue master_queue;
#endif
#if defined(EMP_CONCURRENT_Q)
extern EQ_queue global_cent_queue;
#endif

#ifdef EMP_POP_REC
#define POP_WAIT_QUEUE_SIZE 64

typedef struct {
    unsigned char waitq[POP_WAIT_QUEUE_SIZE];
    unsigned char head;
    unsigned char tail;
} pop_wait_q;

inline int waitq_empty(pop_wait_q *q) { return q->head == q->tail; }

void waitq_push(pop_wait_q *q, unsigned char core_id)
{
    q->waitq[q->tail] = core_id;
    q->tail = (q->tail + 1) % POP_WAIT_QUEUE_SIZE;
}

unsigned char waitq_pop(pop_wait_q *q)
{
    // if (!waitq_empty(q)) {
    unsigned char core_id = q->waitq[q->head];
    q->head = (q->head + 1) % POP_WAIT_QUEUE_SIZE;
    return core_id;
    //}
    // else {
    // return 0;  //It will never appear as core id...
    //}
}

inline unsigned char get_core_id(int row, int col) { return row * 8 + col; }

inline void get_row_col(unsigned char core_id, int *row, int *col)
{
    *row = core_id / 8;
    *col = core_id % 8;
}

#ifdef EMP_PUT_FULL_PROF
void pop_to_wait_core(pop_wait_q *q, EQ_msg_t *msg, uint64_t t, unsigned *put_count,
                      unsigned *put_full)
{
#else
void pop_to_wait_core(pop_wait_q *q, EQ_msg_t *msg, uint64_t t)
{
#endif
    unsigned char pop_id = 0;
    int row, col;
    pop_id = waitq_pop(q);
    get_row_col(pop_id, &row, &col);
    msg->m.op = OP_POP_REPLY;
    msg->m.my_row = row;
    msg->m.my_col = col;
    msg->m.value[0] = t;
    if (row == 0) {
#ifdef EMP_PUT_FULL_PROF
        REG_PUTR(msg->v, msg->m.my_col, put_count, put_full);
#else
        REG_PUTR(msg->v, msg->m.my_col);
#endif
    } else {
#ifdef EMP_PUT_FULL_PROF
        REG_PUTC(msg->v, msg->m.my_row, put_count, put_full);
#else
        REG_PUTC(msg->v, msg->m.my_row);
#endif
    }
}
#endif

void EQ_global_server()
{
    EQ_msg_t msg;
#ifdef EMP_POP_REC
    pop_wait_q waitq;  // assume that stack is all zero
    struct task *pop_task = NULL;
#endif
#ifndef EMP_CONCURRENT_Q
    EQ_queue global_cent_queue;
#endif
#if defined(EMP_MASTER) && !defined(EMP_CONCURRENT_Q)
    EQ_master_queue master_queue;
#endif
#if defined(GLD) || defined(GST)
    unsigned long gld_count1, gld_count2;
    unsigned long gld_gs;
    push_gld = 0;
    pop_gld = 0;
    gld_gs = 0;
#endif

#ifdef GS_MSG_CNT
    unsigned msg_send = 0, msg_recv = 0;
#endif

    int exit_ls, exit_client, col_loop;
#ifdef EMP_MASTER
    EQ_init_queue(&global_cent_queue, 0);
    EQ_init_queue(&master_queue, 1);
#else
    EQ_init_queue(&global_cent_queue);
#endif
    exit_ls = 0;
    exit_client = 0;
#ifdef EMP_WORKER_CONF
    int exit_ls_limit, exit_client_limit;
    exit_client_limit = (WORKERS - 1) / 8 + 1;
    if (WORKERS >= 8)
        exit_ls_limit = 7;
    else
        exit_ls_limit = WORKERS - 1;
#endif
    col_loop = 0;
#ifdef GLD
    penv_slave2_gld_count(&gld_count1);
#elif GST
    penv_slave2_gst_count(&gld_count1);
#endif

#ifdef EMP_PUT_FULL_PROF
    unsigned put_count = 0;
    unsigned put_full = 0;
#endif

    while (1) {
#ifdef EMP_POP_REC
        if (!waitq_empty(&waitq)) {
#ifdef EMP_MASTER
            pop_task = EQ_queue_gs_pop(&global_cent_queue, 0);
#else
            pop_task = EQ_queue_gs_pop(&global_cent_queue);
#endif

            if (pop_task != NULL) {
#ifdef EMP_PUT_FULL_PROF
                pop_to_wait_core(&waitq, &msg, (uint64_t)pop_task, &put_count, &put_full);
#else
                pop_to_wait_core(&waitq, &msg, (uint64_t)pop_task);
#endif
#ifdef GS_MSG_CNT
                msg_send++;
#endif
            }
        }
#endif

        if (!EMPTY_GETR()) {
            REG_GETR(msg.v);

#ifdef GS_MSG_CNT
            msg_recv++;
#endif

            switch (msg.m.op) {
#ifdef EMP_MASTER
                case OP_PUSH_MS:
                    EQ_queue_gs_push(&master_queue, (struct task *)msg.m.value[0], 1);
                    break;
                case OP_PUSH_SL:
#else
                case OP_PUSH:
#endif
#ifdef EMP_POP_REC
                    if (!waitq_empty(&waitq)) {
#ifdef EMP_PUT_FULL_PROF
                        pop_to_wait_core(&waitq, &msg, msg.m.value[0], &put_count, &put_full);
#else
                        pop_to_wait_core(&waitq, &msg, msg.m.value[0]);
#endif

#ifdef GS_MSG_CNT
                        msg_send++;
#endif
                    } else {
#ifdef EMP_MASTER
                        EQ_queue_gs_push(&global_cent_queue, (struct task *)msg.m.value[0], 0);
#else
                        EQ_queue_gs_push(&global_cent_queue, (struct task *)msg.m.value[0]);
#endif
                    }
#else
#ifdef EMP_MASTER
                    EQ_queue_gs_push(&global_cent_queue, (struct task *)msg.m.value[0], 0);
#else
                    EQ_queue_gs_push(&global_cent_queue, (struct task *)msg.m.value[0]);
#endif
#endif
                    break;

#ifdef MULTI_PUSH
                case OP_MULTI_PUSH:
                    EQ_queue_gs_push(&global_cent_queue, (struct task *)msg.m.value[0]);
                    EQ_queue_gs_push(&global_cent_queue, (struct task *)msg.m.value[1]);
                    EQ_queue_gs_push(&global_cent_queue, (struct task *)msg.m.value[2]);
                    break;
#endif
                case OP_POP_REQ:
                    msg.m.op = OP_POP_REPLY;
#ifdef EMP_MASTER
                    msg.m.value[0] = (uint64_t)EQ_queue_gs_pop(&global_cent_queue, 0);
#ifdef MULTI_POP
                    msg.m.value[1] = (uint64_t)EQ_queue_gs_pop(&global_cent_queue, 0);
                    msg.m.value[2] = (uint64_t)EQ_queue_gs_pop(&global_cent_queue, 0);
#endif
#else
                    msg.m.value[0] = (uint64_t)EQ_queue_gs_pop(&global_cent_queue);
#ifdef MULTI_POP
                    msg.m.value[1] = (uint64_t)EQ_queue_gs_pop(&global_cent_queue);
                    msg.m.value[2] = (uint64_t)EQ_queue_gs_pop(&global_cent_queue);
#endif

#endif

#ifdef EMP_POP_REC
                    if (msg.m.value[0] != NULL) {
#ifdef EMP_PUT_FULL_PROF
                        REG_PUTR(msg.v, msg.m.my_col, &put_count, &put_full);
#else
                        REG_PUTR(msg.v, msg.m.my_col);
#endif

#ifdef GS_MSG_CNT
                        msg_send++;
#endif
                    } else {
                        waitq_push(&waitq, get_core_id(msg.m.my_row, msg.m.my_col));
                    }
#else
#ifdef EMP_PUT_FULL_PROF
                    REG_PUTR(msg.v, msg.m.my_col, &put_count, &put_full);
#else
                    REG_PUTR(msg.v, msg.m.my_col);
#endif

#ifdef GS_MSG_CNT
                    msg_send++;
#endif
#endif
                    break;
                case OP_POP_REPLY:
                case OP_EXIT:
                    exit_client++;
#ifdef EMP_WORKER_CONF
                    if (exit_ls >= exit_ls_limit && exit_client >= exit_client_limit) {
#else
                    if (exit_ls >= 7 && exit_client >= 7) {
#endif
                        EQ_destroy_queue();
                        goto gs_exit;
                    }
                    break;
                default:
                    break;
            }
        }

        while (col_loop < 7) {
            col_loop++;
            if (!EMPTY_GETC()) {
                REG_GETC(msg.v);

#ifdef GS_MSG_CNT
                msg_recv++;
#endif

                switch (msg.m.op) {
#ifdef EMP_MASTER
                    case OP_PUSH_MS:
                        EQ_queue_gs_push(&master_queue, (struct task *)msg.m.value[0], 1);
                        break;
                    case OP_PUSH_SL:
#else
                    case OP_PUSH:
#endif
#ifdef EMP_POP_REC
                        if (!waitq_empty(&waitq)) {
#ifdef EMP_PUT_FULL_PROF
                            pop_to_wait_core(&waitq, &msg, msg.m.value[0], &put_count, &put_full);
#else
                            pop_to_wait_core(&waitq, &msg, msg.m.value[0]);
#endif

#ifdef GS_MSG_CNT
                            msg_send++;
#endif
                        } else {
#ifdef EMP_MASTER
                            EQ_queue_gs_push(&global_cent_queue, (struct task *)msg.m.value[0], 0);
#else
                            EQ_queue_gs_push(&global_cent_queue, (struct task *)msg.m.value[0]);
#endif
                        }
#else
#ifdef EMP_MASTER
                        EQ_queue_gs_push(&global_cent_queue, (struct task *)msg.m.value[0], 0);
#else
                        EQ_queue_gs_push(&global_cent_queue, (struct task *)msg.m.value[0]);
#endif
#endif
                        break;
#ifdef MULTI_PUSH
                    case OP_MULTI_PUSH:
                        EQ_queue_gs_push(&global_cent_queue, (struct task *)msg.m.value[0]);
                        EQ_queue_gs_push(&global_cent_queue, (struct task *)msg.m.value[1]);
                        EQ_queue_gs_push(&global_cent_queue, (struct task *)msg.m.value[2]);
                        break;
#endif
                    case OP_POP_REQ:
                        msg.m.op = OP_POP_REPLY;
#ifdef EMP_MASTER
                        msg.m.value[0] = (uint64_t)EQ_queue_gs_pop(&global_cent_queue, 0);
#ifdef MULTI_POP
                        msg.m.value[1] = (uint64_t)EQ_queue_gs_pop(&global_cent_queue, 0);
                        msg.m.value[2] = (uint64_t)EQ_queue_gs_pop(&global_cent_queue, 0);
#endif
#else
                        msg.m.value[0] = (uint64_t)EQ_queue_gs_pop(&global_cent_queue);
#ifdef MULTI_POP
                        msg.m.value[1] = (uint64_t)EQ_queue_gs_pop(&global_cent_queue);
                        msg.m.value[2] = (uint64_t)EQ_queue_gs_pop(&global_cent_queue);
#endif
#endif

#ifdef EMP_POP_REC
                        if (msg.m.value[0] != NULL) {
#ifdef EMP_PUT_FULL_PROF
                            REG_PUTC(msg.v, msg.m.my_row, &put_count, &put_full);
#else
                            REG_PUTC(msg.v, msg.m.my_row);
#endif
#ifdef GS_MSG_CNT
                            msg_send++;
#endif
                        } else {
                            waitq_push(&waitq, get_core_id(msg.m.my_row, msg.m.my_col));
                        }
#else
#ifdef EMP_PUT_FULL_PROF
                        REG_PUTC(msg.v, msg.m.my_row, &put_count, &put_full);
#else
                        REG_PUTC(msg.v, msg.m.my_row);
#endif
#ifdef GS_MSG_CNT
                        msg_send++;
#endif
#endif
                        break;
                    case OP_POP_REPLY:
#ifdef DEBUG
                        assert("global server got pop reply!\n");
#endif
                        break;
                    case OP_EXIT:
                        exit_ls++;
#ifdef EMP_WORKER_CONF
                        if (exit_ls >= exit_ls_limit && exit_client >= exit_client_limit) {
#else
                        if (exit_ls >= 7 && exit_client >= 7) {
#endif
                            EQ_destroy_queue();
                            goto gs_exit;
                        }
                        break;
                    default:
                        break;
                }
            }
        }
        col_loop = 0;

        switch (eq_status) {
            case STATUS_IDLE:
                break;
#ifdef EMP_MASTER
            case STATUS_PUSH_SL:
                EQ_queue_gs_push(&global_cent_queue, (struct task *)eq_ptr_slot, 0);
                eq_status = STATUS_IDLE;
                asm volatile("memb\n");
                break;
            case STATUS_PUSH_MS:
                EQ_queue_gs_push(&master_queue, (struct task *)eq_ptr_slot, 1);
                eq_status = STATUS_IDLE;
                asm volatile("memb\n");
                break;
#else
            case STATUS_PUSH_REQ:
                EQ_queue_gs_push(&global_cent_queue, (struct task *)eq_ptr_slot);
                eq_status = STATUS_IDLE;
                asm volatile("memb\n");
                break;
#endif
            case STATUS_POP_REQ:
#ifdef EMP_MASTER
                eq_ptr_slot = (uint64_t)EQ_queue_gs_pop(&master_queue, 1);
#else
                eq_ptr_slot = (uint64_t)EQ_queue_gs_pop(&global_cent_queue);
#endif
                asm volatile("memb\n");
                eq_status = STATUS_IDLE;
                asm volatile("memb\n");
                break;
#ifdef EMP_POP_REC
            case STATUS_EXIT:
                while (!waitq_empty(&waitq)) {
#ifdef EMP_PUT_FULL_PROF
                    pop_to_wait_core(&waitq, &msg, 0, &put_count, &put_full);
#else
                    pop_to_wait_core(&waitq, &msg, 0);
#endif
                }
                break;
#endif
            default:
                break;
        }

#ifdef EMP_MASTER
        if (m2s_flag == BUFF_STATUS_SL) {
#ifdef HIER_QUEUE_LIFO
            if (m2s_pending.idx <= (global_cent_queue.size - global_cent_queue.tail)) {
#else
            if (m2s_pending.idx <=
                (global_cent_queue.size - (global_cent_queue.tail % global_cent_queue.size))) {
#endif
#if defined(LDM_QUEUE) || defined(HIER_QUEUE_LIFO)
                volatile unsigned long dma_reply = 0;
                int local_tsize = m2s_pending.idx * sizeof(struct task *);
                if (local_tsize > 0) {
#ifdef HIER_QUEUE_LIFO
                    athread_get(0, m2s_pending.buff,
                                global_cent_queue.array + global_cent_queue.tail, local_tsize,
                                (void *)&dma_reply, 0, 0, 0);
#else
                    athread_get(
                        0, m2s_pending.buff,
                        global_cent_queue.array + (global_cent_queue.tail % global_cent_queue.size),
                        local_tsize, (void *)&dma_reply, 0, 0, 0);
#endif
                    while (dma_reply != 1)
                        ;
                }
#else
                memcpy(global_cent_queue.array + (global_cent_queue.tail % global_cent_queue.size),
                       m2s_pending.buff, m2s_pending.idx * sizeof(struct task *));
#endif
                global_cent_queue.tail += m2s_pending.idx;
                m2s_pending.idx = 0;
                asm volatile("memb\n");
                m2s_flag = BUFF_STATUS_MS;
                asm volatile("memb\n");
            }
#ifdef HIER_QUEUE_LIFO
            else {
                int i = 0;
                for (i = 0; i < m2s_pending.idx; i++) {
                    EQ_queue_gs_push(&global_cent_queue, m2s_pending.buff[i], 0);
                }
                m2s_pending.idx = 0;
            }
#else
            else if (m2s_pending.idx > EQ_queue_space(&global_cent_queue)) {
                printf("slave global_cent_queue doesn't have enough space\n");
                fflush(stdout);
                assert(0);
            }
#endif
#ifndef HIER_QUEUE_LIFO
            else
            {  // broken memory space
#ifdef LDM_QUEUE
                volatile unsigned long dma_reply = 0;
                int first_tx =
                    global_cent_queue.size - (global_cent_queue.tail % global_cent_queue.size);
                int local_tsize = first_tx * sizeof(struct task *);
                if (local_tsize > 0) {
                    // athread_get(0, m2s_pending.buff, global_cent_queue.array +
                    // (global_cent_queue.tail % global_cent_queue.size), first_tx * sizeof(struct
                    // task *), &dma_reply, 0, 0, 0);
                    athread_get(
                        0, m2s_pending.buff,
                        global_cent_queue.array + (global_cent_queue.tail % global_cent_queue.size),
                        local_tsize, (void *)&dma_reply, 0, 0, 0);
                    while (dma_reply != 1)
                        ;
                    global_cent_queue.tail += first_tx;
                }
                int second_tx = m2s_pending.idx - first_tx;
                local_tsize = second_tx * sizeof(struct task *);
                if (local_tsize > 0) {
                    athread_get(
                        0, m2s_pending.buff + first_tx,
                        global_cent_queue.array + (global_cent_queue.tail % global_cent_queue.size),
                        second_tx * sizeof(struct task *), &dma_reply, 0, 0, 0);
                    while (dma_reply != 1)
                        ;
                    global_cent_queue.tail += second_tx;
                }
#else
                int first_tx =
                    global_cent_queue.size - (global_cent_queue.tail % global_cent_queue.size);
                memcpy(global_cent_queue.array + (global_cent_queue.tail % global_cent_queue.size),
                       m2s_pending.buff, first_tx * sizeof(struct task *));
                global_cent_queue.tail += first_tx;
                int second_tx = m2s_pending.idx - first_tx;
                memcpy(global_cent_queue.array + (global_cent_queue.tail % global_cent_queue.size),
                       m2s_pending.buff + first_tx, second_tx * sizeof(struct task *));
                global_cent_queue.tail += second_tx;
#endif
                m2s_pending.idx = 0;
                asm volatile("memb\n");
                m2s_flag = BUFF_STATUS_MS;
                asm volatile("memb\n");
            }
#endif
        }
#endif
    }
gs_exit:
#ifdef EMP_PUT_FULL_PROF
    gs_put_count = put_count;
    gs_put_full = put_full;
#endif

#ifdef GLD
    penv_slave2_gld_count(&gld_count2);
    gld[_MYID] = (gld_count2 - gld_count1) - (push_gld + pop_gld);
    // gld[_MYID] = gld_gs;
    printf("push_gld = %lu, pop_gld = %lu\n", push_gld, pop_gld);
#elif GST
    penv_slave2_gst_count(&gld_count2);
    gld[_MYID] = (gld_count2 - gld_count1) - (push_gld + pop_gld);
    // gld[_MYID] = gld_gs;
    printf("push_gld = %lu, pop_gld = %lu\n", push_gld, pop_gld);
#endif

#ifdef GS_MSG_CNT
    printf("Global Server send: %u, recv: %u\n", msg_send, msg_recv);
#endif
    ;
}

void EQ_local_server()
{
    EQ_msg_t msg;
#if defined(GLD) || defined(GST)
    unsigned long gld_count1, gld_count2;
#endif
    int exit_count;
    exit_count = 0;
    int getc_count;
    getc_count = 0;
#ifdef EMP_WORKER_CONF
    int exit_client_limit = (WORKERS - 1) / 8 + 1;
    if (my_row > ((WORKERS - 1) % 8)) exit_client_limit--;
#endif
#ifdef GLD
    penv_slave2_gld_count(&gld_count1);
#elif GST
    penv_slave2_gst_count(&gld_count1);
#endif

#ifdef EMP_PUT_FULL_PROF
    unsigned put_count = 0, put_full = 0;
#endif
    while (1) {
        if (!EMPTY_GETR()) {
            REG_GETR(msg.v);
            if (msg.m.op == OP_EXIT) {
                exit_count++;
#ifdef EMP_WORKER_CONF
                if (exit_count >= exit_client_limit) {
#else
                if (exit_count >= 7) {
#endif

#ifdef EMP_PUT_FULL_PROF
                    REG_PUTC(msg.v, 0, &put_count, &put_full);
#else
                    REG_PUTC(msg.v, 0);
#endif
                    goto ls_exit;
                }
            } else {
#ifdef EMP_PUT_FULL_PROF
                REG_PUTC(msg.v, 0, &put_count, &put_full);
#else
                REG_PUTC(msg.v, 0);
#endif
#ifndef EMP_POP_REC
                if (msg.m.op == OP_POP_REQ) {
                    REG_GETC(msg.v);
#ifdef EMP_PUT_FULL_PROF
                    REG_PUTR(msg.v, msg.m.my_col, &put_count, &put_full);
#else
                    REG_PUTR(msg.v, msg.m.my_col);
#endif
                }
#endif
            }
        }

#ifdef EMP_POP_REC
        if (!EMPTY_GETC()) {
            REG_GETC(msg.v);
            switch (msg.m.op) {
                case OP_POP_REPLY:
#ifdef EMP_PUT_FULL_PROF
                    REG_PUTR(msg.v, msg.m.my_col, &put_count, &put_full);
#else
                    REG_PUTR(msg.v, msg.m.my_col);
#endif
                    break;
                case OP_EXIT:
#ifdef DEBUG
                    assert("local server got col exit\n");
#endif
                    break;
                default:
                    break;
            }
        }
#endif

        /*
        while (getc_count < 16) {
            getc_count++;
            if (!EMPTY_GETC()) {
                REG_GETC(msg.v);
                switch (msg.m.op) {
                    case OP_POP_REPLY:
                        REG_PUTR(msg.v, msg.m.my_col);
                        break;
                    case OP_EXIT:
                    #ifdef DEBUG
                        assert("local server got col exit\n");
                    #endif
                        break;
                    default:
                        break;
                }
            }
        }
        getc_count = 0;
        */
    }
ls_exit:
#ifdef EMP_PUT_FULL_PROF
    ls_put_count[_MYID / 8 - 1] = put_count;
    ls_put_full[_MYID / 8 - 1] = put_full;
#endif

#ifdef GLD
    penv_slave2_gld_count(&gld_count2);
    gld[_MYID] = gld_count2 - gld_count1;
#elif GST
    penv_slave2_gst_count(&gld_count2);
    gld[_MYID] = gld_count2 - gld_count1;
#endif
    ;
}

void EQ_push(struct task *t)
{
    EQ_msg_t msg;
#ifdef EMP_MASTER
    msg.m.op = OP_PUSH_SL;
#else
    msg.m.op = OP_PUSH;
#endif
    msg.m.value[0] = (uint64_t)t;
#ifdef EMP_PUT_FULL_PROF
    REG_PUTR(msg.v, 0, &(worker_put_count[_MYID]), &(worker_put_full[_MYID]));
#else
    REG_PUTR(msg.v, 0);
#endif
}

#ifdef EMP_MASTER
void EQ_push_master(struct task *t)
{
    EQ_msg_t msg;
    msg.m.op = OP_PUSH_MS;
    msg.m.value[0] = (uint64_t)t;
#ifdef EMP_PUT_FULL_PROF
    REG_PUTR(msg.v, 0, &(worker_put_count[_MYID]), &(worker_put_full[_MYID]));
#else
    REG_PUTR(msg.v, 0);
#endif
}
#endif

#ifdef MULTI_PUSH
void EQ_multi_push(struct task *t[3])
{
    EQ_msg_t msg;
    msg.m.op = OP_MULTI_PUSH;
    msg.m.value[0] = (uint64_t)t[0];
    msg.m.value[1] = (uint64_t)t[1];
    msg.m.value[2] = (uint64_t)t[2];
    REG_PUTR(msg.v, 0);
}
#endif

struct task *EQ_pop()
{
    EQ_msg_t msg;
    msg.m.op = OP_POP_REQ;
    msg.m.my_row = my_row;
    msg.m.my_col = my_col;
#ifdef EMP_PUT_FULL_PROF
    REG_PUTR(msg.v, 0, &(worker_put_count[_MYID]), &(worker_put_full[_MYID]));
#else
    REG_PUTR(msg.v, 0);
#endif
    REG_GETR(msg.v);
    return (struct task *)msg.m.value[0];
}

#ifdef MULTI_POP
void EQ_multi_pop(struct task *pop_buff[3])
{
    EQ_msg_t msg;
    msg.m.op = OP_POP_REQ;
    msg.m.my_row = my_row;
    msg.m.my_col = my_col;
    REG_PUTR(msg.v, 0);
    REG_GETR(msg.v);
    pop_buff[0] = (struct task *)msg.m.value[0];
    pop_buff[1] = (struct task *)msg.m.value[1];
    pop_buff[2] = (struct task *)msg.m.value[2];
}
#endif

void EQ_exit()
{
    EQ_msg_t msg;
    msg.m.op = OP_EXIT;
#ifdef EMP_PUT_FULL_PROF
    REG_PUTR(msg.v, 0, &(worker_put_count[_MYID]), &(worker_put_full[_MYID]));
#else
    REG_PUTR(msg.v, 0);
#endif
}

#else

#ifdef HIER_QUEUE_LIFO
struct task *mem_queue[HIER_MEM_QUEUE_SIZE];
__thread_local_fix unsigned mem_queue_tail = 0;
#endif
#include "aceMesh_utils.h"
#define GS_BUFF_SIZE 32
#define CLIENT_BUFF_SIZE 2
extern volatile unsigned long emp_close_master[64];
__thread_local_fix volatile int emp_close;
__thread_local_fix volatile int helper_message=0;
struct chip_buff {
    struct task *task_push[GS_BUFF_SIZE];
    struct task *task_pop;
#ifdef EMP_MASTER
    volatile int op[GS_BUFF_SIZE];
#endif
    volatile int head_push;
    volatile int tail_push;
    volatile int head_pop;
    volatile int tail_pop;
    volatile int pop;
    volatile int exit;
    volatile int push;
};
struct client_buff {
    struct task *task[CLIENT_BUFF_SIZE];
    volatile int head;
    volatile int tail;
};
extern __thread_local_fix int local_total_num_threads;
__thread_local_fix int threads_num = 0;
__uncached volatile long emp_lock[8] __attribute__((aligned(32)));

#ifdef EMP_MASTER
extern __uncached volatile unsigned long suc_buff;
extern __uncached volatile int suc_status;
extern __uncached volatile int suc_num;
#endif
__thread_local_fix int my_role;
// extern __thread_local_share EQ_queue global_cent_queue;  //__attribute__ ((aligned(64)));
__thread_local_fix struct task *buff;
__thread_local_fix struct chip_buff task_buff[64];
#ifdef GS_AGENT
extern __uncached volatile unsigned long con_status;
extern __uncached volatile unsigned long con_dest_ptr;
extern volatile unsigned long con_graph;
extern __uncached volatile unsigned long con_src_ptr;
extern __uncached volatile unsigned long con_task_ptr[MULTI_TASK];
extern __uncached volatile int con_sum_pre;
extern __uncached volatile unsigned long con_task_num;
#endif
// __thread_local_fix volatile int ss_eq_status[64]={STATUS_IDLE};
__thread_local_fix volatile int ss_eq_status=STATUS_IDLE;

extern __thread_local_fix volatile int ss_id_idle;
__thread_local_fix volatile uint64_t ss_eq_ptr_slot;
volatile int eq_status;
volatile uint64_t eq_ptr_slot;

#define remote_ldm(coreid, ldm_var) \
    ((unsigned long)&ldm_var | ((unsigned long)coreid << 20) | (1ULL << 45))
#define remote_ldm_addr(coreid, ldm_var_addr) \
    ((unsigned long)ldm_var_addr | ((unsigned long)coreid << 20) | (1ULL << 45))

#define EQ_start() if (my_role == ROLE_CLIENT) {
#ifdef EMP_MASTER
#define EQ_end()                       \
    }                                  \
    else if (my_role == ROLE_G_SERVER) \
    {                                  \
        EQ_global_server();            \
    }                                  \
    else if (my_role == ROLE_M_SERVER) \
    {                                  \
        EQ_master_server();            \
        EQ_exit();                     \
    }                                  \
    else                               \
    {                                  \
        ;                              \
    }
#else

#define EQ_end()                       \
    }                                  \
    else if (my_role == ROLE_G_SERVER) \
    {                                  \
        EQ_global_server();            \
    }                                  \
    else                               \
    {                                  \
        ;                              \
    }
#endif
#ifdef EMP_QUEUE_PROFILING
unsigned max_length;
#endif

#ifdef EMP_MASTER
//__thread_local_fix volatile int m2s_flag = BUFF_STATUS_MS;
volatile int m2s_flag = BUFF_STATUS_MS;
extern volatile master_buff m2s_pending;
#endif

#ifdef EMP_MASTER
inline int EQ_queue_full(void *queue_ptr, int is_master)
#else
inline int EQ_queue_full(EQ_queue *queue)
#endif
{
#ifdef EMP_MASTER
    if (is_master) {
        EQ_master_queue *queue = (EQ_master_queue *)queue_ptr;
        return (queue->tail - queue->head) == queue->size;
    } else {
        EQ_queue *queue = (EQ_queue *)queue_ptr;
        return (queue->tail - queue->head) == queue->size;
    }
#else
    return (queue->tail - queue->head) == queue->size;
#endif
}

#ifdef EMP_MASTER
inline int EQ_queue_empty(void *queue_ptr, int is_master)
#else
inline int EQ_queue_empty(EQ_queue *queue)
#endif
{
#ifdef EMP_MASTER
    if (is_master) {
        EQ_master_queue *queue = (EQ_master_queue *)queue_ptr;
        return queue->tail == queue->head;
    } else {
        EQ_queue *queue = (EQ_queue *)queue_ptr;
        return queue->tail == queue->head;
    }
#else
    return queue->tail == queue->head;
#endif
}

inline unsigned EQ_queue_length(EQ_queue *queue) { return queue->tail - queue->head; }

#ifdef EMP_MASTER
inline unsigned EQ_queue_space(EQ_queue *queue) { return queue->size - EQ_queue_length(queue); }
#endif

#ifdef EMP_MASTER
void EQ_queue_gs_push(void *queue_ptr, struct task *t, int is_master)
#else
void EQ_queue_gs_push(EQ_queue *queue, struct task *t)
#endif
{
    //   printf("EQ_queue_gs_push******%p\n",t);
#ifdef GLD
    penv_slave2_gld_count(&push_gld_count1);
#elif GST
    penv_slave2_gst_count(&push_gld_count1);
#endif

#ifdef EMP_MASTER

    if (is_master) {
        EQ_master_queue *queue = (EQ_master_queue *)queue_ptr;
#ifdef EMP_CONCURRENT_Q
        slave_my_mutex_lock(&(queue->my_q_lock));
#endif
        if (!EQ_queue_full(queue, 1)) {
            queue->array[queue->tail % queue->size] = t;
            queue->tail++;
        } else {
            printf("master queue full!!!!!!!\n");
        }
#ifdef EMP_CONCURRENT_Q
        slave_my_mutex_unlock(&(queue->my_q_lock));
#endif
    } else {
        EQ_queue *queue = (EQ_queue *)queue_ptr;
#ifdef EMP_CONCURRENT_Q
        slave_my_mutex_lock(&(queue->my_q_lock));
#endif
        if (!EQ_queue_full(queue, 0)) {
#ifdef HIER_QUEUE_LIFO
            queue->array[queue->tail] = t;
#else
            queue->array[queue->tail % queue->size] = t;
#endif
            queue->tail++;
        } else {
#ifdef HIER_QUEUE_LIFO
            if ((HIER_MEM_QUEUE_SIZE - mem_queue_tail) >=
                (INITIAL_QUEUE_SIZE / 2)) {  // still has space
                int tsize = (INITIAL_QUEUE_SIZE / 2) * sizeof(struct task *);
                volatile unsigned long dma_reply = 0;
                athread_put(0, queue->array, mem_queue + mem_queue_tail, tsize, (void *)&dma_reply,
                            0, 0);
                while (dma_reply != 1)
                    ;
                asm volatile("memb\n");  // there has to be a 'memb' here, dunno why
                mem_queue_tail += INITIAL_QUEUE_SIZE / 2;
                memcpy(queue->array, queue->array + INITIAL_QUEUE_SIZE / 2, tsize);
                queue->tail = INITIAL_QUEUE_SIZE / 2;
                queue->array[queue->tail] = t;
                queue->tail++;
            } else {
                printf("slave mem queue full!!!!!!!\n");
            }
#else
            printf("slave queue full!!!!!!!\n");
#endif
        }
#ifdef EMP_CONCURRENT_Q
        slave_my_mutex_unlock(&(queue->my_q_lock));
#endif
    }

#else
#ifdef EMP_CONCURRENT_Q
    slave_my_mutex_lock(&(queue->my_q_lock));
#endif
    if (!EQ_queue_full(queue)) {
#ifdef HIER_QUEUE_LIFO
        queue->array[queue->tail] = t;
    
#else
        queue->array[queue->tail % queue->size] = t;
#endif
        queue->tail++;
        //  printf("队列%d任务%p\n",queue->tail,t);
#ifdef EMP_QUEUE_PROFILING
        unsigned qlen = EQ_queue_length(queue);
        if (max_length < qlen) max_length = qlen;
#endif

#ifdef GLD
        penv_slave2_gld_count(&push_gld_count2);
        push_gld += push_gld_count2 - push_gld_count1;
#elif GST
        penv_slave2_gst_count(&push_gld_count2);
        push_gld += push_gld_count2 - push_gld_count1;
#endif
    } else {
#ifdef HIER_QUEUE_LIFO
        if ((HIER_MEM_QUEUE_SIZE - mem_queue_tail) >= (INITIAL_QUEUE_SIZE / 2)) {  // still has
                                                                                   // space
            int tsize = (INITIAL_QUEUE_SIZE / 2) * sizeof(struct task *);
            volatile unsigned long dma_reply = 0;
            athread_put(0, queue->array, mem_queue + mem_queue_tail, tsize, (void *)&dma_reply, 0,
                        0);
            while (dma_reply != 1)
                ;
            asm volatile("memb\n");  // there has to be a 'memb' here, dunno why
            mem_queue_tail += INITIAL_QUEUE_SIZE / 2;
            memcpy(queue->array, queue->array + INITIAL_QUEUE_SIZE / 2, tsize);
            queue->tail = INITIAL_QUEUE_SIZE / 2;
            queue->array[queue->tail] = t;
            queue->tail++;
        } else {
            printf("mem queue full!!!!!!!\n");
        }
#else
        printf("queue full!!!!!!!\n");
#endif
#ifdef GLD
        penv_slave2_gld_count(&push_gld_count2);
        push_gld += push_gld_count2 - push_gld_count1;
#elif GST
        penv_slave2_gst_count(&push_gld_count2);
        push_gld += push_gld_count2 - push_gld_count1;
#endif
#ifdef EMP_CONCURRENT_Q
        slave_my_mutex_unlock(&(queue->my_q_lock));
#endif
        return;
    }
#ifdef EMP_CONCURRENT_Q
    slave_my_mutex_unlock(&(queue->my_q_lock));
#endif
#endif
}

#ifdef EMP_MASTER
struct task *EQ_queue_gs_pop(void *queue_ptr, int is_master)
#else
struct task *EQ_queue_gs_pop(EQ_queue *queue)
#endif
{
    // printf("MYID%dEQ_queue_gs_pop\n",_MYID);
#ifdef EMP_MASTER
    if (is_master) {
        EQ_master_queue *queue = (EQ_master_queue *)queue_ptr;
#ifdef EMP_CONCURRENT_Q
        slave_my_mutex_lock(&(queue->my_q_lock));
#endif
        if (!EQ_queue_empty(queue, 1)) {
            struct task *temp = queue->array[queue->head % queue->size];
            queue->head++;
#ifdef EMP_CONCURRENT_Q
            slave_my_mutex_unlock(&(queue->my_q_lock));
#endif
            return temp;
        } else {
#ifdef EMP_CONCURRENT_Q
            slave_my_mutex_unlock(&(queue->my_q_lock));
#endif
            return NULL;
        }
    } else {
        EQ_queue *queue = (EQ_queue *)queue_ptr;
#ifdef EMP_CONCURRENT_Q
        slave_my_mutex_lock(&(queue->my_q_lock));
#endif

        if (!EQ_queue_empty(queue, 0)) {
#ifdef HIER_QUEUE_LIFO
            queue->tail = queue->tail - 1;
            struct task *temp = queue->array[queue->tail];
#else
            struct task *temp = queue->array[queue->head % queue->size];
            queue->head++;
#endif
#ifdef EMP_CONCURRENT_Q
            slave_my_mutex_unlock(&(queue->my_q_lock));
#endif
            return temp;
        } else {
#ifdef HIER_QUEUE_LIFO
            if (mem_queue_tail >= (INITIAL_QUEUE_SIZE / 2)) {  // mem queue not empty
                int tsize = (INITIAL_QUEUE_SIZE / 2) * sizeof(struct task *);
                volatile unsigned long dma_reply = 0;
                mem_queue_tail -= INITIAL_QUEUE_SIZE / 2;
                athread_get(0, mem_queue + mem_queue_tail, queue->array, tsize, (void *)&dma_reply,
                            0, 0, 0);
                while (dma_reply != 1)
                    ;
                asm volatile("memb\n");  // there has to be a 'memb' here, dunno why
                queue->tail = INITIAL_QUEUE_SIZE / 2;
                queue->tail = queue->tail - 1;
                struct task *temp = queue->array[queue->tail];
#ifdef EMP_CONCURRENT_Q
                slave_my_mutex_unlock(&(queue->my_q_lock));
                assert(0);
#endif
                return temp;
            } else {
#ifdef EMP_CONCURRENT_Q
                slave_my_mutex_unlock(&(queue->my_q_lock));
                assert(0);
#endif
                return NULL;
            }
#endif
#ifdef EMP_CONCURRENT_Q
            slave_my_mutex_unlock(&(queue->my_q_lock));
#endif
            return NULL;
        }
    }

#else

#ifdef GLD
    penv_slave2_gld_count(&pop_gld_count1);
#elif GST
    penv_slave2_gst_count(&pop_gld_count1);
#endif

#ifdef EMP_CONCURRENT_Q
    slave_my_mutex_lock(&(queue->my_q_lock));
#endif

    if (!EQ_queue_empty(queue)) {
#ifdef HIER_QUEUE_LIFO
        queue->tail = queue->tail - 1;
        struct task *temp = queue->array[queue->tail];
        printf("MYID%dEQ_queue_ga_pop%p\n",_MYID,temp);
#else
        struct task *temp = queue->array[queue->head % queue->size];
        queue->head++;
        printf("MYID%dEQ_queue_gs_pop%p\n",_MYID,temp);
#endif
#ifdef GLD
        penv_slave2_gld_count(&pop_gld_count2);
        pop_gld += pop_gld_count2 - pop_gld_count1;
#elif GST
        penv_slave2_gst_count(&pop_gld_count2);
        pop_gld += pop_gld_count2 - pop_gld_count1;
#endif
#ifdef EMP_CONCURRENT_Q
        slave_my_mutex_unlock(&(queue->my_q_lock));
#endif
        return temp;
    } else {
#ifdef GLD
        penv_slave2_gld_count(&pop_gld_count2);
        pop_gld += pop_gld_count2 - pop_gld_count1;
#elif GST
        penv_slave2_gst_count(&pop_gld_count2);
        pop_gld += pop_gld_count2 - pop_gld_count1;
#endif
#ifdef HIER_QUEUE_LIFO
        if (mem_queue_tail >= (INITIAL_QUEUE_SIZE / 2)) {  // mem queue not empty
            int tsize = (INITIAL_QUEUE_SIZE / 2) * sizeof(struct task *);
            volatile unsigned long dma_reply = 0;
            mem_queue_tail -= INITIAL_QUEUE_SIZE / 2;
            athread_get(0, mem_queue + mem_queue_tail, queue->array, tsize, (void *)&dma_reply, 0,
                        0, 0);
            while (dma_reply != 1)
                ;
            asm volatile("memb\n");  // there has to be a 'memb' here, dunno why
            queue->tail = INITIAL_QUEUE_SIZE / 2;
            queue->tail = queue->tail - 1;
            struct task *temp = queue->array[queue->tail];
#ifdef EMP_CONCURRENT_Q
            slave_my_mutex_unlock(&(queue->my_q_lock));
            assert(0);
#endif
            return temp;
        } else {
#ifdef EMP_CONCURRENT_Q
            slave_my_mutex_unlock(&(queue->my_q_lock));
            assert(0);
#endif
            return NULL;
        }
#endif
#ifdef EMP_CONCURRENT_Q
        slave_my_mutex_unlock(&(queue->my_q_lock));
#endif
        return NULL;
    }

#endif
}

void EQ_begin()
{
    // int core_id;
    // core_id = athread_get_id(-1);
    // my_row = ROW(core_id);
    // my_col = COL(core_id);
    /*
    #ifdef EMP_WORKER_CONF
        int trans_id = (my_col - 1) * 8 + my_row;
        int local_server_limit;
        if (WORKERS >= 8)
            local_server_limit = 7;
        else
            local_server_limit = WORKERS - 1;
        if (core_id == 0) {
            my_role = ROLE_G_SERVER;
        }
        else if (my_col == 0 && my_row <= local_server_limit) {
            my_role = ROLE_L_SERVER;
        }
        else if (my_col != 0 && trans_id < WORKERS) {
            my_role = ROLE_CLIENT;
        }
        else {
            my_role = ROLE_DEFAULT;
        }
    #else

      */
#if defined(CONCURRENT_CONSTRUCT_GRAPH) && !defined(GS_AGENT)
    threads_num = local_total_num_threads - 1;
#else
    threads_num = local_total_num_threads;
#endif
    emp_close = 0;
    emp_close_master[_MYID] = &emp_close;

    // printf("threads_num:%d,local_total_num_threads:%d\n",threads_num,local_total_num_threads);
    if (_MYID == 0) {
        my_role = ROLE_G_SERVER;
    }
#ifdef EMP_MASTER
    else if (_MYID == threads_num - 1) {
        my_role = ROLE_M_SERVER;
    }
#endif
    else {
        my_role = ROLE_CLIENT;
    }
    // #endif
    // printf("my_id:%d my_role:%d\n",_MYID,my_role);
}

#ifdef EMP_MASTER
inline void EQ_init_queue(void *queue_ptr, int is_master)
#else
inline void EQ_init_queue(EQ_queue *queue)
#endif
{
    int i, j;
    for (i = 0; i < local_total_num_threads; i++) {
        task_buff[i].head_push = 0;
        task_buff[i].tail_push = 0;
        task_buff[i].head_pop = 0;
        task_buff[i].tail_pop = 0;
        //    task_buff[i].push = 0;
        task_buff[i].pop = 0;
        task_buff[i].exit = 0;
        task_buff[i].push = 0;
        //   ss_eq_status[i]=STATUS_IDLE; //不能在这里初始化
#ifdef EMP_MASTER
        for (j = 0; j < GS_BUFF_SIZE; j++) {
            task_buff[i].op[j] = 0;
        }
#endif
        // task_buff[i].send_num=0;
        // task_buff[i].recv_num=0;
       // ss_eq_status=STATUS_IDLE;
    }

#ifdef EMP_MASTER
    if (is_master) {
        EQ_master_queue *queue = (EQ_master_queue *)queue_ptr;
#if !defined(LDM_QUEUE) && !defined(HIER_QUEUE_LIFO)  // MMEM_QUEUE
        queue->array = master_big_array;
#ifdef EMP_CONCURRENT_Q
        queue->my_q_lock = 0;
#endif
#endif
        queue->head = 0;
        queue->tail = 0;
        queue->size = INITIAL_MASTER_QUEUE_SIZE;
        eq_status = STATUS_IDLE;
    } else {
        EQ_queue *queue = (EQ_queue *)queue_ptr;
#if !defined(LDM_QUEUE) && !defined(HIER_QUEUE_LIFO)  // MMEM_QUEUE
        queue->array = big_array;
#ifdef EMP_CONCURRENT_Q
        queue->my_q_lock = 0;
#endif
#endif
        queue->head = 0;
        queue->tail = 0;
        queue->size = INITIAL_QUEUE_SIZE;
        eq_status = STATUS_IDLE;
    }

#else

#if !defined(LDM_QUEUE) && !defined(HIER_QUEUE_LIFO)  // MMEM_QUEUE
    queue->array = big_array;
#ifdef EMP_CONCURRENT_Q
    queue->my_q_lock = 0;
#endif
#endif
    queue->head = 0;
    queue->tail = 0;
    queue->size = INITIAL_QUEUE_SIZE;
    eq_status = STATUS_IDLE;
  
#ifdef EMP_QUEUE_PROFILING
    max_length = 0;
#endif

#endif
}

inline void EQ_destroy_queue()
{
    // FreePool();
    ;
}

#if defined(EMP_MASTER) && defined(EMP_CONCURRENT_Q)
extern EQ_master_queue master_queue;
#endif
#if defined(EMP_CONCURRENT_Q)
extern EQ_queue global_cent_queue;
#endif

__thread_local_fix int worker_tail[4][16] = {0};
__thread_local_fix int server_head[4][16] = {0};
__thread_local_fix volatile int worker_pop[4][16] = {0};
__thread_local_fix int server_pop[4][16]={0};
#define group _MYID / 16
#define site _MYID % 16
__thread_local_fix unsigned long push_qu_temp=0,push_qu_time=0,judge_time=0;
__thread_local_fix int push_qu_times=0;
#ifdef SLAVE_CONSTRUCT_HELEPR
//  volatile int begin_execute2[64];
//  volatile int begin_execute1[64];

#endif

#ifdef EMP_MASTER
void recvtask(void *queue_ptr1, void *queue_ptr2, int thread_id, int type)
#else
void recvtask(void *queue_ptr, int thread_id, int type)
#endif
{
/*
if(type==2){
struct task *t = NULL;
struct chip_buff *self = NULL;

}else{
*/
#ifdef SIMD_RECV
    int i, j = 0;
    struct task *t = NULL;
    struct chip_buff *self = NULL;
    int512 lresult,judge=1;
    intv16 vres, vres_keep;
    intv16 *vhead, *vtail;
    for (i = 0; i < 4;) {
        vhead = (intv16 *)&server_head[i][0];
        vtail = (intv16 *)&worker_tail[i][0];
        vres = simd_vcmpltw(*vhead, *vtail);  // vhead < vtail;
       push_qu_temp=rtc();
       if (simd_reduc_plusw(vres) == 0) {
            judge_time+=rtc()-push_qu_temp;
            push_qu_times++;
            i++;
            continue;
        }
        vres_keep = vres;
       
        lresult = (int512)vres;
        int addr=0,cur = 0;
        int temp;
       while (addr!=512) {
        // while(simd_reduc_plusw(lresult)!=0){
         // lresult=lresult>>32;
            temp = (int)lresult;
            lresult = lresult >> 32;
            addr += 32;
            if(temp==1){
            self = &task_buff[i * 16 + cur];
            t = self->task_push[server_head[i][cur] % GS_BUFF_SIZE];
            EQ_queue_gs_push(queue_ptr, t);
            }
            cur = cur + 1;
        }
        
        *vhead = *vhead + vres_keep;
        i++;
        continue;
    }
#else
    
    struct chip_buff *self = NULL;
    struct chip_buff *hope = NULL;
    struct task *t = NULL;
    int local_head = 0, l_head = 0;
    int local_tail = 0;
    int i = 1;
    int op = 0;
/*
if(type==2){

self = &task_buff[local_total_num_threads-1];

while(self->head_push!=self->tail_push){
t = self->task_push[self->head_push];
self->head_push = (self->head_push + 1) % GS_BUFF_SIZE;
EQ_queue_gs_push(queue_ptr, t);

}
}else{
*/
#ifdef GS_AGENT
    for (i = 1; i < local_total_num_threads;) {
#else
#ifdef EMP_LOCK
    for (i = 0; i < 8;) {
#else
    for (i = 1; i < local_total_num_threads;) {
#endif
//   for(i=thread_id;i<thread_id+16;){
#endif
        self = &task_buff[i];
        local_head = self->head_push;
        // l_head=(local_head+1)%GS_BUFF_SIZE;
        // local_tail=self->tail_push;
        if (local_head == self->tail_push) {  //||l_head==local_tail) {
            i++;
            continue;
        }
        t = self->task_push[local_head];
#ifdef EMP_MASTER
        op = self->op[local_head];
#endif
        self->head_push = (local_head + 1) % GS_BUFF_SIZE;
#ifdef EMP_MASTER
        if (op)
            EQ_queue_gs_push(queue_ptr2, t, op);
        else
            EQ_queue_gs_push(queue_ptr1, t, op);
#else
       push_qu_temp=rtc();
       printf("!!!!!!!!!!!recvtask%p\n",t);
        EQ_queue_gs_push(queue_ptr, t);
        printf("!!!!!!!!!!!afterrecvtask%p\n",t);
        push_qu_time+=rtc()-push_qu_temp;
        push_qu_times++;
      
#endif
#ifdef SLAVE_CONSTRUCT_HELEPR
        // }
        //   }
#endif
       
    }
#endif
//}
}
#ifdef EMP_PROFILING
__thread_local_fix unsigned long pop_time = 0, push_time = 0, tmp_, once_pop_time = 0,
                                 once_push_time = 0, once_remote_time = 0;
__thread_local_fix int buffer_full_num = 0;
#endif
// volatile int spawn_end=0;
#ifdef GS_AGENT
#define my_atomic_add(_new_, _addr_)                                                \
    {                                                                               \
        asm volatile("faal   %0,0(%1)\n\t" : "=r"(_new_) : "r"(_addr_) : "memory"); \
        _new_++;                                                                    \
    }
#endif
extern volatile unsigned long master_spawn;
//__thread_local_fix unsigned long push_qu_temp=0,push_qu_time=0;
//__thread_local_fix int push_qu_times=0;
__thread_local_fix volatile int helper_spawn_end=0;
//volatile 很有必要加！！！！！！！！！！！！
void EQ_global_server()
{
    // printf("******EQ_global_server\n");
    // EQ_msg_t msg;
    // EQ_queue global_cent_queue;
    int i = 0;
#ifdef GS_AGENT
    int val = 1;
    int sub = 1;
    //   int i=0;
    // close=1;
    volatile int con_close;
    volatile unsigned long con_ptr;
    volatile int status;
    con_graph = &con_close;
    con_status = &status;
    con_src_ptr = &con_ptr;
    // printf("con_graph:%ld\n",con_graph);
#ifdef MULTI_SPAWN
    volatile unsigned long task_ptr[MULTI_TASK];
    volatile int task_num;
    for (i = 0; i < MULTI_TASK; i++) con_task_ptr[i] = &task_ptr[i];
    con_task_num = &task_num;
    task_num = 0;
#endif
    //   con_close=1;
    status = 0;
#endif
#ifndef EMP_CONCURRENT_Q
    EQ_queue global_cent_queue;
#endif
#if defined(EMP_MASTER) && !defined(EMP_CONCURRENT_Q)
    EQ_master_queue master_queue;
#endif
#if defined(GLD) || defined(GST)
    unsigned long gld_count1, gld_count2;
    unsigned long gld_gs;
    push_gld = 0;
    pop_gld = 0;
    gld_gs = 0;
#endif

#ifdef GS_MSG_CNT
    unsigned msg_send = 0, msg_recv = 0;
#endif

    int exit_ls, exit_client, col_loop;
#ifdef EMP_MASTER
    EQ_init_queue(&global_cent_queue, 0);
    EQ_init_queue(&master_queue, 1);
#else
    EQ_init_queue(&global_cent_queue);
#endif
// printf("#######%dMYID退出%d\n",_MYID,eq_status);
    // init_end=1;
    // asm volatile("memb\n");
    volatile int spawn_end = 0;
    master_spawn = &spawn_end;
    int j, num = 0;
    struct chip_buff *self = NULL;
    struct task *t = NULL;
    int local_tail;
    int eq_exit = 0;
    int thread_id = 0;
    int scan_null = 0;
#ifdef EMP_PROFILING
    unsigned long master_time = 0, all_time = 0, recv_time = 0, min_recv_time = 0, for_time = 0,
                  temp = 0, once_recv_time = 0, once_for_time = 0;
    int times = 0;
    int null_num = 0;
    all_time = rtc();
#endif
 unsigned long recv=0,temp_recv=0,pop=0,pop_temp=0;
 int recv_num=0,pop_num=0;
    intv16 *s_pop;
    intv16 w_pop=0;
    int512 result;
    intv16 temp_pop;
    // for(int i=0;i<64;i++){
    // begin_execute1[i]=1;
    // begin_execute2[i]=1;
    // }
    while (1) {
#ifdef EMP_PROFILING
        temp = rtc();
#endif
        //      thread_id=thread_id%4;
       // temp_recv=rtc();
    //  printf("recvtask****************************\n");
        recvtask(&global_cent_queue, thread_id * 16, 1);
    
    //    printf("recvtaskend****************************\n");  
      //  recv+=rtc()-temp_recv;
       // recv_num++;
       // printf("recv_cyccle:%ld\n",recv);
#ifdef EMP_PROFILING
        recv_time = recv_time + rtc() - temp;
        if (times == 0) min_recv_time = recv_time;
        if (times == 20000) once_recv_time = rtc() - temp;
        temp = rtc();
#endif
pop_temp=rtc();
pop_num++;
#ifdef SIMD_POP
       // pop_temp=rtc();
        for (i = 0; i < 4; i++) {
           // w_pop = (intv16 *)&worker_pop[i][0];
          // w_pop=2;
           simd_load(w_pop,&(worker_pop[i][0]));
           //s_pop=(intv16 *)&server_pop[i][0];
          // simd_print_intv16(w_pop);
           //temp_pop=w_pop;//simd_vcmpltw(*s_pop, *w_pop);
           if (simd_reduc_plusw(w_pop) != 0) {
           //int ww=simd_ctlzow(w_pop);
           //  simd_print_intv16(w_pop);
           // temp_pop=(*server_pop);
            result = (int512)(w_pop);
            // simd_print_int512(result);
                int  cur = 0;
                long temp;
                while (simd_reduc_plusw(result)!=0) {
                  // simd_print_int512(result);
                    temp = (long)result;
                    result = result >> 64;
                    //addr += 64;
                    // site++;
                    if (temp == 1) {
                        self = &task_buff[i * 16 + cur];
                        t = EQ_queue_gs_pop(&global_cent_queue);
                        if (t != NULL || emp_close) {
                            self->task_pop = t;
                          worker_pop[i][cur] = 0;
                       //  printf("pop:%d\n",worker_pop[i][cur]);
                          //asm volatile("memb\n");
                        }
                        
                        else {
                            recvtask(&global_cent_queue, thread_id * 16, 1);
                            t = EQ_queue_gs_pop(&global_cent_queue);
                            if (t != NULL || emp_close) {
                                self->task_pop = t;
                                worker_pop[i][cur] = 0;
                         //      printf("pop:%d\n",worker_pop[i][cur]);
                               //asm volatile("memb\n");
                            }
                        }
                        
                    } else if (temp == 4294967296) {
                        self = &task_buff[i * 16 + cur + 1];
                        t = EQ_queue_gs_pop(&global_cent_queue);
                        if (t != NULL || emp_close) {
                            self->task_pop = t;
                            worker_pop[i][cur+1] = 0;
                         //printf("pop:%d\n",worker_pop[i][cur+1]);
                         //   asm volatile("memb\n");
                        }
                        
                        else {
                            recvtask(&global_cent_queue, thread_id * 16, 1);
                            t = EQ_queue_gs_pop(&global_cent_queue);
                            if (t != NULL || emp_close) {
                                self->task_pop = t;
                                worker_pop[i][cur+1] = 0;
                         //    printf("pop:%d\n",worker_pop[i][cur+1]);
                             //   asm volatile("memb\n");
                            }
                        }
                        
                    } else if (temp == 4294967297) {
                        self = &task_buff[i * 16 + cur];
                        t = EQ_queue_gs_pop(&global_cent_queue);
                        if (t != NULL || emp_close) {
                            self->task_pop = t;
                             worker_pop[i][cur] = 0;
                        // printf("pop:%d\n",worker_pop[i][cur]);
                         //   asm volatile("memb\n");
                        }
                        
                        else {
                            recvtask(&global_cent_queue, thread_id * 16, 1);
                            t = EQ_queue_gs_pop(&global_cent_queue);
                            if (t != NULL || emp_close) {
                                self->task_pop = t;
                                worker_pop[i][cur] = 0;
                          //   printf("pop:%d\n",worker_pop[i][cur]);
                             //  asm volatile("memb\n");
                            }
                        }
                        
                        self = &task_buff[i * 16 + cur + 1];
                       t = EQ_queue_gs_pop(&global_cent_queue);
                        if (t != NULL || emp_close) {
                            self->task_pop = t;
                          worker_pop[i][cur+1] = 0;
                        // printf("pop:%d\n",worker_pop[i][cur+1]);
                         //  asm volatile("memb\n");
                        } 
                        
                        else {
                            recvtask(&global_cent_queue, thread_id * 16, 1);
                            t = EQ_queue_gs_pop(&global_cent_queue);
                            if (t != NULL || emp_close) {
                                self->task_pop = t;
                            worker_pop[i][cur+1] = 0;
                          // printf("pop:%d\n",worker_pop[i][cur+1]);
                           //   asm volatile("memb\n");
                            }
                        }
                        
                    }
                    cur = cur + 2;
                }
                 // *w_pop=*w_pop-temp_pop;
                 //  asm volatile("memb\n");
              //    printf("after\n");
                 // simd_print_intv16(*w_pop);
            // for(j=0;j++;j<16)
            //printf("worker_pop:%d",worker_pop[i][0]);
            }
        }
        //printf("after_pop\n");

#else
        //long spop=0;
        //    for(i=thread_id*16;i<thread_id*16+16;i++) {
// #ifdef SLAVE_CONSTRUCT_HELEPR
        //  for (i = 1; i <8 ; i++) { //复合任务被映射到第一行从核当中
// #else
        for (i = 1; i < local_total_num_threads; i++) {
            //  printf("MEQ_queue_gs_pop%d\n",i);
// #endif
#if defined(GS_AGENT) && defined(CONCURRENT_CONSTRUCT_GRAPH)
           
#endif
            //spop=(long)worker_pop[2*i];
            //if(spop!=0)
            self = &task_buff[i];
            if (self->pop == IDLE) {
                //   printf("self->pop == IDLE%d\n",i);
                // local_tail = (self->tail_pop + 1) % GS_BUFF_SIZE;
#ifdef EMP_MASTER
                // if (EQ_queue_empty(&global_cent_queue, 0)) {
                //   recvtask(&global_cent_queue,&master_queue);
                //  }
                t = EQ_queue_gs_pop(&global_cent_queue, 0);
#else
                // if (EQ_queue_empty(&global_cent_queue)) {
                //     recvtask(&global_cent_queue);
                // }
                //  printf("MEQ_queue_gs_pop1:%p\n",t);
                t = EQ_queue_gs_pop(&global_cent_queue);
                //  printf("MEQ_queue_gs_pop11:%p\n",t);
#endif
// #ifdef SLAVE_CONSTRUCT_HELEPR
               // if (t != NULL || emp_close||global_heleper[i]) {
// #else
                if (t != NULL || emp_close) {
// #endif             
#ifdef SLAVE_CONSTRUCT_HELEPR
                    int tasktype=get_task_type((struct aceMesh_task *)t);
                    int ct=0;
                    if(tasktype==COMPOSITE_TASK){
                        // if(i>=1&&i<=7){          
                         struct chip_buff *ct_buff= NULL;
                         struct chip_buff *tl_buff= NULL;
                         ct=i%8;  //映射到1-7号从核
                        if(ct==0) ct=i/8; //如果映射到0号从核,则重新映射
                         ct_buff=&task_buff[ct];
#ifdef DEBUG_PBH
                    printf("任务%p是复合任务,ct%d,i%d,pop%d\n",t,ct,i,ct_buff->pop);
                            fflush(stdout);
#endif
                         //for(ct=1;ct<8;ct++){
                           
                            if(ct_buff->pop==IDLE){
                            struct chip_buff *helper_pop= NULL;
#ifdef DISTRIBUTE_TOP
                            helper_pop = &task_buff[ct+1];
                            helper_pop->pop=TOP_LEVEL_HELPER;
#endif
                            int j;
                            for(j=ct*8;j<HELPER_NUM+ct*8;j++){  //启动i+1之后的HELPER_NUM个从核作为helper
                            //给helper发送pop请求
                            assert(j<local_total_num_threads);
                            helper_pop = &task_buff[j];
                            helper_pop->pop=HELPER;
#ifdef DEBUG_PBH
                            printf("EQ_global_server开启%d号helper\n",j);
                            fflush(stdout);

#endif
                            // int *helper_begin=remote_ldm(j, helper_flag);
                            // *helper_begin=1;
                            // asm volatile("memb\n");
                            // int *global_flag=remote_ldm(j, global_heleper);
                            // *global_flag=1;
                            // asm volatile("memb\n");
                           
                            // int *helper_begin1=remote_ldm(i, global_heleper[i]);
                            // *helper_begin1=1;
                            }
                                ct_buff->task_pop = t;
                                ct_buff->pop = COMPOSITE_TASK;
                            }else{
                                // EQ_queue_gs_push(&global_cent_queue, (struct task *)t);
                                 //continue; 
                            }    

                    }else{
// #ifdef DEBUG_PBH
//                             printf("NORMAL_TASK POP to %d:%p\n",i,t);
//                             fflush(stdout);

// #endif                        
                        self->task_pop = t;
                        self->pop = NORMAL_TASK;
                    }

                    
                    // self->tail_pop = (self->tail_pop+1)%GS_BUFF_SIZE;
                    // local_tail = (local_tail + 1) % GS_BUFF_SIZE;
#else
                    self->task_pop = t;
                    self->pop = NORMAL_TASK;
#endif
                    
                    // break;
                } else {
#ifdef EMP_MASTER
                    recvtask(&global_cent_queue, &master_queue);
#else
                    recvtask(&global_cent_queue, thread_id * 16, 1);
#endif
                    //  printf("MEQ_queue_gs_pop2:%p\n",t);
                    t = EQ_queue_gs_pop(&global_cent_queue);
                    //  printf("MEQ_queue_gs_pop22:%p\n",t);
                      
                if (t != NULL || emp_close) {
#ifdef SLAVE_CONSTRUCT_HELEPR
                    int tasktype=get_task_type((struct aceMesh_task *)t);
                      int ct=0;
                    if(tasktype==COMPOSITE_TASK){
                    // if(i>=1&&i<=7){
                        struct chip_buff *ct_buff= NULL;
                        ct=i%8;  //映射到1-7号从核
                        if(ct==0) ct=i/8; //如果映射到0号从核
                        ct_buff=&task_buff[ct];
                        // for(ct=1;ct<8;ct++){
#ifdef DEBUG_PBH
                    printf("#任务%p是复合任务,ct%d,i%d,pop%d\n",t,ct,i,ct_buff->pop);
                            fflush(stdout);

#endif
                        
                        if(ct_buff->pop==IDLE){
                        struct chip_buff *helper_pop= NULL;
#ifdef DISTRIBUTE_TOP
                            helper_pop = &task_buff[ct+1];
                            helper_pop->pop=TOP_LEVEL_HELPER;
#endif
                        int j;
                         // for(j=i+1;j<HELPER_NUM+i+1;j++){  //启动i+1之后的HELPER_NUM个从核作为helper
                        for(j=ct*8;j<HELPER_NUM+ct*8;j++){  //启动i+1之后的HELPER_NUM个从核作为helper
                        assert(j<local_total_num_threads);
                        //给helper发送pop请求
                            helper_pop = &task_buff[j];
                            helper_pop->pop=HELPER;
#ifdef DEBUG_PBH
                            printf("#EQ_global_server开启%d号helper\n",j);
                            fflush(stdout);
#endif
                            // int *helper_begin=remote_ldm(j, helper_flag);
                            // *helper_begin=1;
                            // asm volatile("memb\n");
                            // int *global_flag=remote_ldm(j, global_heleper);
                            // *global_flag=1;
                            // asm volatile("memb\n");
                           
                            // int *helper_begin1=remote_ldm(i, global_heleper[i]);
                            // *helper_begin1=1;
                        }
                            ct_buff->task_pop = t;
                            ct_buff->pop = COMPOSITE_TASK;
                        }else{
                           // EQ_queue_gs_push(&global_cent_queue, (struct task *)t);
                             //continue;
                        }

                    }else{
// #ifdef DEBUG_PBH
//                             printf("#NORMAL_TASK POP to %d:%p\n",i,t);
//                             fflush(stdout);

// #endif  
                        self->task_pop = t;
                        self->pop = NORMAL_TASK;
                    }

                    
                    // self->tail_pop = (self->tail_pop+1)%GS_BUFF_SIZE;
                    // local_tail = (local_tail + 1) % GS_BUFF_SIZE;
#else
                    self->task_pop = t;
                    self->pop = NORMAL_TASK;
#endif
                        // break;
                    }
                }
                // break;
            }
            // #ifdef EMP_PROFILING
            // else{
            //   scan_null++;
            // }
            // #endif
            //    if (self->exit == 1) {
            //      eq_exit++;
            //    self->exit = 0;
            //  printf("exit:%d\n",eq_exit);
            //  }
#if defined(GS_AGENT) && defined(CONCURRENT_CONSTRUCT_GRAPH)
            // self=&task_buff[0];
            // while(self->head_push!=self->tail_push){
            // t=self->task_push[self->head_push];
            // self->head_push=(self->head_push+1)%GS_BUFF_SIZE;
            // EQ_queue_gs_push(&global_cent_queue, t);
            // }
            switch (status) {
                case 0:
                    break;
                case 1:
                    slave_my_mutex_lock((volatile int *)con_ptr);
                    asm volatile("memb\n");
                    //   printf("slave_lock\n");
                    status = 0;
                    asm volatile("memb\n");
                    break;
                case 2:
                    my_atomic_add(con_sum_pre, (volatile int *)con_ptr);
                    asm volatile("memb\n");
                    status = 0;
                    asm volatile("memb\n");
                    break;
                case 3:
#ifdef MULTI_SPAWN
                    for (i = 0; i < task_num; i++) {
                        // slave_spawn_to_id((struct task *)task_ptr[i]);
                        EQ_queue_gs_push(&global_cent_queue, (struct task *)task_ptr[i]);
                    }
#else
                    // slave_spawn_to_id((struct task *)con_ptr);
                    EQ_queue_gs_push(&global_cent_queue, (struct task *)con_ptr);
#endif
                    asm volatile("memb\n");
                    status = 0;
                    asm volatile("memb\n");
                    break;
                case 4:
                    slave_my_mutex_unlock((volatile int *)con_ptr);
                    asm volatile("memb\n");
                    status = 0;
                    asm volatile("memb\n");
                    break;
                case 5:
                    updt_subw(sub, (volatile int *)con_ptr);  // slave.h
                    asm volatile("memb\n");
                    status = 0;
                    asm volatile("memb\n");
                    break;
                default:
                    status = 0;
                    asm volatile("memb\n");
                    break;
            }
                // }
#endif
        }
/*
#ifdef SLAVE_CONSTRUCT_HELEPR
         for (i = 8; i <local_total_num_threads ; i++) {
            self = &task_buff[i];
            if (self->pop == IDLE) {
                // local_tail = (self->tail_pop + 1) % GS_BUFF_SIZE;
#ifdef EMP_MASTER
                // if (EQ_queue_empty(&global_cent_queue, 0)) {
                //   recvtask(&global_cent_queue,&master_queue);
                //  }
                t = EQ_queue_gs_pop(&global_cent_queue, 0);
#else
                // if (EQ_queue_empty(&global_cent_queue)) {
                //     recvtask(&global_cent_queue);
                // }
                t = EQ_queue_gs_pop(&global_cent_queue);
#endif
                if (t != NULL || emp_close) {

                    int tasktype=get_task_type((struct aceMesh_task *)t);
                    if(tasktype!=COMPOSITE_TASK){                  
                        self->task_pop = t;
                    // self->tail_pop = (self->tail_pop+1)%GS_BUFF_SIZE;
                    // local_tail = (local_tail + 1) % GS_BUFF_SIZE;

                        self->pop = NORMAL_TASK;
                    }
                    // break;
                } else {
#ifdef EMP_MASTER
                    recvtask(&global_cent_queue, &master_queue);
#else
                    recvtask(&global_cent_queue, thread_id * 16, 1);
#endif
                    t = EQ_queue_gs_pop(&global_cent_queue);
                    int tasktype=get_task_type((struct aceMesh_task *)t);
                    if(tasktype!=COMPOSITE_TASK){                  
                        self->task_pop = t;
                    // self->tail_pop = (self->tail_pop+1)%GS_BUFF_SIZE;
                    // local_tail = (local_tail + 1) % GS_BUFF_SIZE;

                        self->pop = NORMAL_TASK;
                    }
                }
                // break;
            }
         }
#endif
*/
#endif
pop+=rtc()-pop_temp;
       
#ifdef EMP_PROFILING
        for_time = for_time + rtc() - temp;
        times++;
        if (times == 20000) once_for_time = rtc() - temp;
#endif

        if (emp_close) {
            EQ_destroy_queue();
            printf("exit:%d num:%d\n", eq_exit, num);
            goto gs_exit;
        }
#ifdef EMP_PROFILING
        temp = rtc();
#endif
#ifndef CONCURRENT_CONSTRUCT_GRAPH
#if !defined(EMP_MASTER ) && !defined(REUSE_GRAPH)
// printf("!!!!!!!!!!spawn_end%d\n",spawn_end);
#ifdef FLAT_CONSTRUCT_HELEPR
        while (!helper_spawn_end) { //只有top任务会用到下面的？
#else
        while (!spawn_end) {   
#endif
            
#endif

#ifdef FLAT_CONSTRUCT_HELEPR
//   printf("%dss_eq_status%d\n",_MYID,ss_eq_status[7]);   
                switch (ss_eq_status) {
                    
                case STATUS_IDLE:
                    break;
#ifdef EMP_MASTER
                case STATUS_PUSH_SL:
                    //   printf("push_sl\n");
                    EQ_queue_gs_push(&global_cent_queue, (struct task *)ss_eq_ptr_slot, 0);
                    ss_eq_status= STATUS_IDLE;
                    asm volatile("memb\n");
                    break;
                case STATUS_PUSH_MS:
                    //   printf("push_ms\n");
                    EQ_queue_gs_push(&master_queue, (struct task *)ss_eq_ptr_slot, 1);
                    ss_eq_status = STATUS_IDLE;
                    asm volatile("memb\n");
                    break;
#else
            case STATUS_PUSH_REQ:
                printf("EQ_queue_gs_push%p\n", (struct task *)ss_eq_ptr_slot);
                EQ_queue_gs_push(&global_cent_queue, (struct task *)ss_eq_ptr_slot);
                ss_eq_status= STATUS_IDLE;
                // ss_eq_status = STATUS_IDLE;
                int *is_idle=remote_ldm(7,ss_eq_status);
                 *is_idle=STATUS_IDLE;
                asm volatile("memb\n");
                break;
#endif
                case STATUS_POP_REQ:
#ifdef EMP_MASTER
                    // printf("emp_master_pop\n");
                ss_eq_ptr_slot = (uint64_t)EQ_queue_gs_pop(&master_queue, 1);
#else
                ss_eq_ptr_slot = (uint64_t)EQ_queue_gs_pop(&global_cent_queue);
#endif
                    asm volatile("memb\n");
                    ss_eq_status = STATUS_IDLE;
                    asm volatile("memb\n");
                    break;
                default:
                    break;
            }
            //  printf("switch****************************\n");
#else
            //flush_slave_cache();
            switch (eq_status) {
                 printf("eq_statuseq_statuseq_statuseq_status\n");
                case STATUS_IDLE:
                    break;
#ifdef EMP_MASTER
                case STATUS_PUSH_SL:
                    //   printf("push_sl\n");
                    EQ_queue_gs_push(&global_cent_queue, (struct task *)eq_ptr_slot, 0);
                    eq_status = STATUS_IDLE;
                    asm volatile("memb\n");
                    break;
                case STATUS_PUSH_MS:
                    //   printf("push_ms\n");
                    EQ_queue_gs_push(&master_queue, (struct task *)eq_ptr_slot, 1);
                    eq_status = STATUS_IDLE;
                    asm volatile("memb\n");
                    break;
#else
            case STATUS_PUSH_REQ:
                 printf("push_sl\n");
                EQ_queue_gs_push(&global_cent_queue, (struct task *)eq_ptr_slot);
                eq_status = STATUS_IDLE;
                asm volatile("memb\n");
                break;
#endif
                case STATUS_POP_REQ:
#ifdef EMP_MASTER
                    // printf("emp_master_pop\n");
                    eq_ptr_slot = (uint64_t)EQ_queue_gs_pop(&master_queue, 1);
#else
                eq_ptr_slot = (uint64_t)EQ_queue_gs_pop(&global_cent_queue);
#endif
                    asm volatile("memb\n");
                    eq_status = STATUS_IDLE;
                    asm volatile("memb\n");
                    break;
                default:
                    break;
            }

#endif
#ifdef EMP_PROFILING
            master_time = master_time + rtc() - temp;
#endif
#if !defined(EMP_MASTER)&& !defined(REUSE_GRAPH)
        }
        // printf("****************************\n");
#endif
#endif

#if defined(GS_AGENT) && defined(CONCURRENT_CONSTRUCT_GRAPH)
        switch (status) {
            case 0:
                break;
            case 1:
                slave_my_mutex_lock((volatile int *)con_ptr);
                asm volatile("memb\n");
                // printf("slave_lock\n");
                status = 0;
                asm volatile("memb\n");
                break;
            case 2:
                my_atomic_add(con_sum_pre, (volatile int *)con_ptr);
                asm volatile("memb\n");
                status = 0;
                asm volatile("memb\n");
                break;
            case 3:
#ifdef MULTI_SPAWN
                for (i = 0; i < task_num; i++) {
                    // slave_spawn_to_id((struct task *)task_ptr[i]);
                    EQ_queue_gs_push(&global_cent_queue, (struct task *)task_ptr[i]);
                }
#else
                // slave_spawn_to_id((struct task *)con_ptr);
                EQ_queue_gs_push(&global_cent_queue, (struct task *)con_ptr);
#endif
                asm volatile("memb\n");
                status = 0;
                asm volatile("memb\n");
                break;
            case 4:
                slave_my_mutex_unlock((volatile int *)con_ptr);
                asm volatile("memb\n");
                status = 0;
                asm volatile("memb\n");
                break;
            case 5:
                updt_subw(sub, (volatile int *)con_ptr);  // slave.h
                asm volatile("memb\n");
                status = 0;
                asm volatile("memb\n");
                break;
            default:
                status = 0;
                asm volatile("memb\n");
                break;
        }
            // }
#endif

        /*
        #ifdef EMP_MASTER
                if (m2s_flag == BUFF_STATUS_SL) {
        #ifdef HIER_QUEUE_LIFO
                    if (m2s_pending.idx <= (global_cent_queue.size - global_cent_queue.tail)) {
        #else
                    if (m2s_pending.idx <=
                        (global_cent_queue.size - (global_cent_queue.tail %
        global_cent_queue.size))) { #endif #if defined(LDM_QUEUE) || defined(HIER_QUEUE_LIFO)
                        volatile unsigned long dma_reply = 0;
                        int local_tsize = m2s_pending.idx * sizeof(struct task *);
                        if (local_tsize > 0) {
        #ifdef HIER_QUEUE_LIFO
                            athread_get(0, m2s_pending.buff,
                                        global_cent_queue.array + global_cent_queue.tail,
        local_tsize, (void *)&dma_reply, 0, 0, 0); #else athread_get( 0, m2s_pending.buff,
                                global_cent_queue.array + (global_cent_queue.tail %
        global_cent_queue.size), local_tsize, (void *)&dma_reply, 0, 0, 0); #endif while (dma_reply
        != 1)
                                ;
                        }
        #else
                        memcpy(global_cent_queue.array + (global_cent_queue.tail %
        global_cent_queue.size), m2s_pending.buff, m2s_pending.idx * sizeof(struct task *)); #endif
                        global_cent_queue.tail += m2s_pending.idx;
                        m2s_pending.idx = 0;
                        asm volatile("memb\n");
                        m2s_flag = BUFF_STATUS_MS;
                        asm volatile("memb\n");
                    }
        #ifdef HIER_QUEUE_LIFO
                    else {
                        int i = 0;
                        for (i = 0; i < m2s_pending.idx; i++) {
                            EQ_queue_gs_push(&global_cent_queue, m2s_pending.buff[i], 0);
                        }
                        m2s_pending.idx = 0;
                    }
        #else
                    else if (m2s_pending.idx > EQ_queue_space(&global_cent_queue)) {
                        printf("slave global_cent_queue doesn't have enough space\n");
                        fflush(stdout);
                        assert(0);
                    }
        #endif
        #ifndef HIER_QUEUE_LIFO
                    else
                    {  // broken memory space
        #ifdef LDM_QUEUE
                        volatile unsigned long dma_reply = 0;
                        int first_tx =
                            global_cent_queue.size - (global_cent_queue.tail %
        global_cent_queue.size); int local_tsize = first_tx * sizeof(struct task *); if (local_tsize
        > 0) {
                            // athread_get(0, m2s_pending.buff, global_cent_queue.array +
                            // (global_cent_queue.tail % global_cent_queue.size), first_tx *
        sizeof(struct
                            // task *), &dma_reply, 0, 0, 0);
                            athread_get(
                                0, m2s_pending.buff,
                                global_cent_queue.array + (global_cent_queue.tail %
        global_cent_queue.size), local_tsize, (void *)&dma_reply, 0, 0, 0); while (dma_reply != 1)
                                ;
                            global_cent_queue.tail += first_tx;
                        }
                        int second_tx = m2s_pending.idx - first_tx;
                        local_tsize = second_tx * sizeof(struct task *);
                        if (local_tsize > 0) {
                            athread_get(
                                0, m2s_pending.buff + first_tx,
                                global_cent_queue.array + (global_cent_queue.tail %
        global_cent_queue.size), second_tx * sizeof(struct task *), &dma_reply, 0, 0, 0); while
        (dma_reply != 1)
                                ;
                            global_cent_queue.tail += second_tx;
                        }
        #else
                        int first_tx =
                            global_cent_queue.size - (global_cent_queue.tail %
        global_cent_queue.size); memcpy(global_cent_queue.array + (global_cent_queue.tail %
        global_cent_queue.size), m2s_pending.buff, first_tx * sizeof(struct task *));
                        global_cent_queue.tail += first_tx;
                        int second_tx = m2s_pending.idx - first_tx;
                        memcpy(global_cent_queue.array + (global_cent_queue.tail %
        global_cent_queue.size), m2s_pending.buff + first_tx, second_tx * sizeof(struct task *));
                        global_cent_queue.tail += second_tx;
        #endif
                        m2s_pending.idx = 0;
                        asm volatile("memb\n");
                        m2s_flag = BUFF_STATUS_MS;
                        asm volatile("memb\n");
                    }
        #endif
                }
        #endif
        */
    }
gs_exit:
 // printf("recv:%ld,recv_num:%d\n",recv,recv_num);
//printf("server:pop:%ld,pop_num:%d,ave_pop:%ld\n",pop,pop_num,pop/pop_num);
//printf("server:judge_times:%d,judge_time:%ld\n",push_qu_times,judge_time);
#ifdef EMP_PROFILING
    all_time = rtc() - all_time;
    printf(
        "gs_server: "
        "all_time:%ld,master_time:%ld,min_recv_time:%ld,once_recv_time:%ld,recv_time:%ld,for_time:%"
        "ld,once_for_time:%ld\n",
        all_time, master_time, min_recv_time, once_recv_time, recv_time, for_time, once_for_time);
// for(i=0;i<100;i++)
// printf("%d,null_num:%d\n",i,null_num[i]);
#endif
#ifdef GS_MSG_CNT
    printf("Global Server send: %u, recv: %u\n", msg_send, msg_recv);
#endif
    ;
}

#ifdef EMP_MASTER
//#define my_atomic_add(_new_, _addr_)                                                \
    {                                                                               \
            asm volatile("faal   %0,0(%1)\n\t" : "=r"(_new_) : "r"(_addr_) : "memory"); \
                    _new_++;                                                                    \
                        }
void EQ_master_server()
{
    struct aceMesh_task *ms;
    printf("EQ_master_server\n");
    while (!emp_close) {
        if (suc_status) {
            printf("suc_status\n");
            fflush(stdout);

            ms = (struct aceMesh_task *)suc_buff;
            asm volatile("memb\n");
            // slave_execute((struct aceMesh_task *)suc_buff);

            suc_status = 0;
            asm volatile("memb\n");
            slave_execute(ms);
            /*
            my_atomic_add(suc_num,(volatile int *)suc_buff);
            asm volatile("memb\n");
            suc_status=0;
            asm volatile("memb\n");
            printf("after_suc_status,ms:%x\n",ms);
            fflush(stdout);
            */
        }
    }
}

void EQ_push_master(struct task *t)
{
    printf("EQ_push_master\n");
    struct chip_buff *self = remote_ldm(0, task_buff[_MYID]);
    int local_tail = (self->tail_push + 1) % GS_BUFF_SIZE;
    while (self->head_push == local_tail)
        ;
    self->task_push[self->tail_push] = t;
    self->op[self->tail_push] = 1;
    self->tail_push = local_tail;
}
#endif
__thread_local_fix unsigned long lock_time = 0, once_other_time = 0, once_while_time = 0,
                                 once_task_time = 0,lock_temp=0;
__thread_local_fix int lock_num=0;
void EQ_push(struct task *t)  //调用这个
{
//lock_temp=rtc();
//lock_num++;
#ifdef SIMD_RECV
    struct chip_buff *self = remote_ldm(0, task_buff[_MYID]);
    int *tail = remote_ldm(0, worker_tail[group][site]);
    int *head = remote_ldm(0, server_head[group][site]);
    while (*tail - *head == GS_BUFF_SIZE - 1)
        ;
    self->task_push[*tail % GS_BUFF_SIZE] = t;
    *tail = *tail + 1;
#else
#ifdef EMP_LOCK
    //lock_temp=rtc();
    //lock_num++;
    while (CRTS_smutex_lock_row())
        ;
// slave_my_mutex_lock(&emp_lock[_ROW]);
// lock_time=rtc()-lock_time;
#endif
 //    printf("EQ_push:%d,%x\n",_MYID,t);
#ifdef EMP_PROFILING
    tmp_ = rtc();
#endif
#if !defined(EMP_MASTER) && !defined(CONCURRENT_CONSTRUCT_GRAPH)
    // if (buff == NULL) {
    //  buff = t;
    // } else {
#endif
    // printf("EQ_push_%d\n",_MYID);
 
#ifdef EMP_LOCK

    struct chip_buff *self = remote_ldm(0, task_buff[_ROW]);
#else
    struct chip_buff *self = remote_ldm(0, task_buff[_MYID]);
#endif
#ifdef EMP_PROFILING
    once_remote_time = rtc() - tmp_;
#endif
    // once_other_time=rtc();
    int local_tail = (self->tail_push + 1) % GS_BUFF_SIZE;
    //   once_other_time=rtc()-once_other_time;
#ifdef EMP_PROFILING
    if (self->head_push == local_tail) buffer_full_num++;
#endif
    // once_while_time=rtc();
    while (self->head_push == local_tail)
        ;
    // once_while_time=rtc()-once_while_time;
    //      once_task_time=rtc();
    // while(begin_execute[_MYID]==0)
    //    ;
    self->task_push[self->tail_push] = t;
       
    
#ifdef EMP_MASTER
    self->op[self->tail_push] = 0;
#endif
    self->tail_push = local_tail;
     printf("tail%dEQ_push_%p\n",self->tail_push,t);
// once_task_time=rtc()-once_task_time;
#if !defined(EMP_MASTER) && !defined(CONCURRENT_CONSTRUCT_GRAPH)
    //  }
#endif
#ifdef EMP_PROFILING
    once_push_time = rtc() - tmp_;
    // if(_MYID==1)
    //  printf("once_push_time:%ld\n",once_push_time);
    push_time = push_time + rtc() - tmp_;
    // once_push_time=rtc()-tmp_;
// printf("once_push_time:%ld\n",once_push_time);
#endif
#ifdef EMP_LOCK
    CRTS_smutex_unlock_row();
// slave_my_mutex_unlock(&emp_lock[_ROW]);
//lock_time+=rtc()-lock_temp;
#endif
#endif
//lock_time+=rtc()-lock_temp;
// printf("%d_push:%p\n",_MYID,t);
}

void EQ_pop_front()
{
    // struct chip_buff *self;
    // self = remote_ldm(0, task_buff[_MYID]);
    // self->pop = 1;
}
__thread_local_fix int pop_num = 0;
__thread_local_fix unsigned long pop_l=0,l_temp=0;
__thread_local_fix int index_id1=0; 
// __thread_local_fix int buffer_sizes[HELPER_NUM] = {0};
__thread_local_fix int index_task=0;  
struct task *EQ_pop() //调用这个接收task
{  
 //   pop_num++;
    struct task *t;
#ifdef EMP_PROFILING
    tmp_ = rtc();
#endif
#if !defined(EMP_MASTER) && !defined(CONCURRENT_CONSTRUCT_GRAPH)
    //  if (buff == NULL) {
#endif
   // printf("EQ_pop_%d\n",_MYID);
    struct chip_buff *self;

    self = remote_ldm(0, task_buff[_MYID]);
    // if(self->head_pop==self->tail_pop){
    // if(self->head_push==self->tail_push){
#ifdef SIMD_POP
    //printf("pop_begin\n");
    int *wpop=remote_ldm(0, worker_pop[group][site]);
    //int *spop=t=remote_ldm(0,server_pop[group][site]);
    // *wpop = 0;
    // int num=0; 
     *wpop=1;
    l_temp=rtc();
    int *temp;
    //*temp=1;
    //printf("%d,pop:%d\n",_MYID,*wpop);
    // while ((self->head_pop==self->tail_pop)&& self->pop)
    while (!emp_close)
    {
    
    temp=remote_ldm(0, worker_pop[group][site]);
    
    if(*temp==0)
      break;
   // num++;
   // if(num==10000)
   // break;
   //if(_MYID==1) 
   //printf("POP:%d",*wpop);
   }
   if(pop_num>1&&pop_num<12)
   pop_l+=rtc()-l_temp;
   //printf("pop\n");
    if (*temp == 0 && !emp_close) {
#else
    self->pop=IDLE;
    // global_heleper=0;
   // l_temp=rtc();
// #ifdef SLAVE_CONSTRUCT_HELEPR
//      int *gh=remote_ldm(_MYID,global_heleper);
//      asm volatile("memb\n");
    // while(self->pop&& !emp_close&&!global_heleper[_MYID]);
//      while(self->pop&& !emp_close&&!gh);
// #else
// printf("%dMYID pop IDLE???\n",self->pop);
    while(self->pop==IDLE&& !emp_close);
// #endif
    //  printf("EQ_pop_after%d\n",_MYID);
  //  if(pop_num>1&&pop_num<12)
  //  pop_l+=rtc()-l_temp;

 if(self->pop==NORMAL_TASK&& !emp_close){
   // printf("%dNORMAL_TASK_POP%p\n",_MYID,self->task_pop);
#endif
#ifdef SLAVE_CONSTRUCT_HELEPR
// printf("EQ_POP_NORMAL_TASK%p\n",self);
// int local_head = self->head_pop;
        t = self->task_pop;
         self->task_pop =NULL;
         
#ifdef EMP_PROFILING
        pop_time = pop_time + rtc() - tmp_;
        if (pop_num == 5) once_pop_time = rtc() - tmp_;
        if (_MYID == 1) printf("once_pop_time:%ld\n", once_pop_time);
#endif
        //printf("%d_pop,%p\n",_MYID,t);
        return t;
    } else if(self->pop==COMPOSITE_TASK&& !emp_close){
        t = self->task_pop;
#ifdef DEBUG_PBH.
printf("EQ_POP_COMPOSITE_TASK%p,MYID%d\n",t,_MYID);
       fflush(stdout);

#endif
        self->task_pop =NULL;
       
#ifdef EMP_PROFILING
        pop_time = pop_time + rtc() - tmp_;
        if (pop_num == 5) once_pop_time = rtc() - tmp_;
        if (_MYID == 1) printf("once_pop_time:%ld\n", once_pop_time);
#endif
        //printf("%d_pop,%p\n",_MYID,t);
        return t;
    }else if(self->pop==HELPER&& !emp_close){
        // if(helper_flag==1){
#ifdef DEBUG_PBH
         printf("EQ_POP_HELPER启动helper%d,轮询\n",_MYID);
            fflush(stdout);

#endif
      //  if(8<=_MYID&&_MYID<(HELPER_NUM+8)){ //启动helper，轮询
            init_slave_buffer();  //从核初始化
            worker_help_func();  
            
#ifdef DEBUG_PBH
            printf("worker_help_func%d调用结束\n",_MYID);
            fflush(stdout);

#endif
           
            return NULL;
            // helper_flag=0;
            // struct chip_buff *helper_pop_change= NULL;
            // helper_pop_change = &task_buff[_MYID];
            // helper_pop_change->pop=0;
            // int *global_flag=remote_ldm(_MYID, global_heleper[_MYID]);
            // *global_flag=0;
            // asm volatile("memb\n");
       // }       
        // }

    }
#ifdef DISTRIBUTE_TOP
    else if(self->pop==TOP_LEVEL_HELPER&& !emp_close){
        printf("******接收top_task%d******\n",_MYID);
        init_tl_buffer();
        // init_buffer_tasks()
        struct task *latent_top[HELPER_NUM][4096]; 
         int buffer_sizes[HELPER_NUM] = {0};
        struct top_level_buff* self=NULL;
        int local_head=0,i;
         struct task *top_task=NULL;
         while(!top_sig){
        for(i=0; i<NT; i++){ 
            self=&tl_buffer[(i + index_id1)%NT];  //当前从核的环形队列
            int buffer_id=(i + index_id1)%NT;
            local_head=self->head;
            //printf("****接收****头指针%d,尾指针%d\n",local_head,self->tail);
            if(self->tail==local_head){//当从核环形队列没有元素，则查找下一个队列

                continue;
            }
            top_task=self->top_task[local_head]; 
           //printf("****接收任务%p****buffer%dindex%d\n",top_task,buffer_id,index_id1);
  
        //    if (buffer_tasks_list[buffer_id].head == NULL) {  
        //      // 如果链表为空，则新任务是头也是尾  
        //         buffer_tasks_list[buffer_id].head = task;  
        //         buffer_tasks_list[buffer_id].tail = task;  
        //     } else {  
        //         // 否则，添加到链表尾部  
        //         buffer_tasks_list[buffer_id].tail->next = task;  
        //         buffer_tasks_list[buffer_id].tail = task;  
        //     } 
        
            //每个helper的cur_top单独存放在一个临时数组里，共需要HELPER_NUM个临时数组
            latent_top[buffer_id][buffer_sizes[buffer_id]++]=top_task; 
            
            assert(buffer_sizes[buffer_id]<4096);
            self->head=(local_head+1)%HELPER_BUFF_SIZE;  //head指针+1，取下一个元素
		    index_id1++;
           // printf("#buffer%dlatent top个数%d\n",buffer_id,buffer_sizes[buffer_id]);
        }
         }
         printf("总DA数index%d\n",index_id1);
         for( i=8*(_MYID-1);i<8*(_MYID-1)+HELPER_NUM;i++){
          printf("buffer%dlatent top个数%d\n",i,buffer_sizes[i]);
         }
         printf("******开始去重*****\n");
         //构图结束后，采用归并的方法，对这HELPER_NUM个数组两两去重
         int common_count=0;
         task **common_tasks = find_common_tasks(latent_top,buffer_sizes, &common_count);
        for (int i = 0; i < common_count; i++) {  
        printf("Common task address: %p\n", (void*)common_tasks[i]);  
    } 
        //struct task* merged_buffers[64] = {NULL};  
        // printf("log(HELPER_NUM) + 1:%d\n",log(HELPER_NUM) + 1);
        //  struct task *merged_buffers[HELPER_NUM][4096]; 
        // int merged_sizes[HELPER_NUM] = {0};
          //merged_buffers[0][4096] = merge_and_deduplicate(latent_top[0], buffer_sizes[0], latent_top[1], buffer_sizes[1], &merged_sizes[0]);  
        //    merged_buffers[1][4096] = merge_and_deduplicate(latent_top[2], buffer_sizes[2], latent_top[3], buffer_sizes[3], &merged_sizes[1]);  
        //    merged_buffers[2][4096] = merge_and_deduplicate(latent_top[4], buffer_sizes[4], latent_top[5], buffer_sizes[5], &merged_sizes[2]);  
        //    merged_buffers[3][4096] = merge_and_deduplicate(latent_top[6], buffer_sizes[6], latent_top[7], buffer_sizes[7], &merged_sizes[3]);  
        //    merged_buffers[4][4096] = merge_and_deduplicate(merged_buffers[0], merged_sizes[0], merged_buffers[1], merged_sizes[1], &merged_sizes[4]);  
        //    merged_buffers[5][4096] = merge_and_deduplicate(merged_buffers[2], merged_sizes[2], merged_buffers[3], merged_sizes[3], &merged_sizes[5]);  
        //    merged_buffers[6][4096] = merge_and_deduplicate(merged_buffers[4], merged_sizes[4], merged_buffers[5], merged_sizes[5], &merged_sizes[6]);  

    }
#endif
   else{
#ifdef EMP_PROFILING
        pop_time = pop_time + rtc() - tmp_;
        // once_pop_time=rtc()-tmp_;
#endif
        return NULL;
    }
#else
// int local_head = self->head_pop;
        t = self->task_pop;
         self->task_pop =NULL;
#ifdef EMP_PROFILING
        pop_time = pop_time + rtc() - tmp_;
        if (pop_num == 5) once_pop_time = rtc() - tmp_;
        if (_MYID == 1) printf("once_pop_time:%ld\n", once_pop_time);
#endif
        //printf("%d_pop,%p\n",_MYID,t);
        return t;
    } else {
#ifdef EMP_PROFILING
        pop_time = pop_time + rtc() - tmp_;
        // once_pop_time=rtc()-tmp_;
#endif
        return NULL;
    }
#endif
    /*
   }else{
     int local_tail = (self->tail_push+GS_BUFF_SIZE-1)%GS_BUFF_SIZE;
     //t = self->task_pop[self->head_pop];
     //self->head_pop=(self->head_pop+1)%GS_BUFF_SIZE;
     t=self->task_push[local_tail];
     self->tail_push=local_tail;

     return t;
   }
   */
#if !defined(EMP_MASTER) && !defined(CONCURRENT_CONSTRUCT_GRAPH)
    // } else {
    //      t = buff;
    //      buff = NULL;
    //     return t;
    // }
#endif
}

void EQ_exit()
{
    //    struct chip_buff *self = remote_ldm(0, task_buff[_MYID]);
    //  self->exit = 1;
//  printf("%d,pop_latency:%ld,pop_num:%d\n",_MYID,pop_l,pop_num);
 //  printf("%d,emp_rowlock:%ld,num:%d\n",_MYID,lock_time,lock_num);
#ifdef EMP_PROFILING
    printf(
        "%d:push_time:%ld,pop_time:%ld,once_push_time:%ld,once_remote_time:%ld,once_othre_time:%ld,"
        "once_while_time:%ld,once_task_time:%ld,once_pop_time:%ld,buffer_full_num:%d\n",
        _MYID, push_time, pop_time, once_push_time, once_remote_time, once_other_time,
        once_while_time, once_task_time, once_pop_time, buffer_full_num);

#endif
}

#endif
#endif
